/** * Copyright 2004-2016 Riccardo Solmi. All rights reserved. * This file is part of the Whole Platform. * * The Whole Platform is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The Whole Platform is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>. */ /** * */ package org.whole.lang.xsd.codebase; import static org.whole.lang.commons.parsers.CommonsDataTypePersistenceParser.*; import static org.whole.lang.xsd.mapping.reflect.MappingEntityDescriptorEnum.*; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.whole.lang.reflect.EntityDescriptor; import org.whole.lang.reflect.FeatureDescriptor; import org.whole.lang.xsd.mapping.model.AnyMapping; import org.whole.lang.xsd.mapping.model.ContentMapping; import org.whole.lang.xsd.mapping.model.Mapping; import org.whole.lang.xsd.mapping.model.Mappings; import org.whole.lang.xsd.mapping.model.MixedStructuralMapping; import org.whole.lang.xsd.mapping.model.RootMapping; import org.whole.lang.xsd.mapping.model.TypeMapping; import org.whole.lang.xsd.mapping.visitors.MappingIdentityDefaultVisitor; import org.whole.lang.xsd.util.SchemaUtils; /** * @author Enrico Persiani */ public class MappingIndexes { private final Map<MappingIndexes.IndexTypes, Map<Object, Set<CompiledMapping>>> indexes; public MappingIndexes() { indexes = new HashMap<MappingIndexes.IndexTypes, Map<Object, Set<CompiledMapping>>>(); } public CompiledMapping add(EntityDescriptor<?> mappingType, EntityDescriptor<?> context, EntityDescriptor<?> ed, FeatureDescriptor fd, String ncname) { return add(new CompiledMapping(mappingType, context, ed, fd, ncname)); } public CompiledMapping add(Mapping mapping) { return add(new CompiledMapping(mapping)); } public void addAll(Mappings mappings) { for (int i=0, size=mappings.wSize(); i<size; i++) { Mapping mapping = (Mapping) mappings.wGet(i); switch (mapping.wGetEntityDescriptor().getOrdinal()) { case UnionMapping_ord: break; default: add(mapping); break; } } } public Set<CompiledMapping> findMappings(EntityDescriptor<?> mappingType, EntityDescriptor<?> context, String ncname) { Set<CompiledMapping> byContext = getMappings(IndexTypes.CONTEXT, context); Set<CompiledMapping> result = new HashSet<CompiledMapping>(getMappings(IndexTypes.NCNAME, ncname)); Iterator<CompiledMapping> iterator = result.iterator(); while (iterator.hasNext()) { CompiledMapping m = iterator.next(); if (!mappingType.equals(m.mappingType) || !byContext.contains(m)) iterator.remove(); } return result; } public CompiledMapping findMapping(EntityDescriptor<?> mappingType, EntityDescriptor<?> context, String ncname) { Set<CompiledMapping> byContext = getMappings(IndexTypes.CONTEXT, context); for (CompiledMapping m : getMappings(IndexTypes.NCNAME, ncname)) if (mappingType.equals(m.mappingType) && (byContext.contains(m))) return m; return CompiledMapping.NULL; } public CompiledMapping findMapping(EntityDescriptor<?> mappingType, EntityDescriptor<?> context) { for (CompiledMapping m : getMappings(IndexTypes.CONTEXT, context)) if (mappingType.equals(m.mappingType)) return m; return CompiledMapping.NULL; } public CompiledMapping findMapping(String ncname) { for (CompiledMapping m : getMappings(IndexTypes.NCNAME, ncname)) if (RootMapping.equals(m.mappingType)) return m; return CompiledMapping.NULL; } public CompiledMapping findMapping(EntityDescriptor<?> ed) { for (CompiledMapping m : getMappings(IndexTypes.ED, ed)) if (RootMapping.equals(m.mappingType)) return m; return CompiledMapping.NULL; } public CompiledMapping findMapping(EntityDescriptor<?> mappingType, EntityDescriptor<?> context, EntityDescriptor<?> ed, FeatureDescriptor fd) { Set<CompiledMapping> byEntity = getMappings(IndexTypes.ED, ed); Set<CompiledMapping> byFeature = getMappings(IndexTypes.FD, fd); for (CompiledMapping m : getMappings(IndexTypes.CONTEXT, context)) if (mappingType.equals(m.mappingType) && (byEntity.contains(m) || (m.ed.isAbstract() && m.ed.isPlatformSupertypeOf(ed))) && (m.fd == null || // would be CommonsFeatureDescriptorEnum.any byFeature.contains(m))) return m; return CompiledMapping.NULL; } private Map<Object, Set<CompiledMapping>> getIndex(MappingIndexes.IndexTypes indexType) { Map<Object, Set<CompiledMapping>> index = indexes.get(indexType); if (index == null) indexes.put(indexType, index = new HashMap<Object, Set<CompiledMapping>>()); return index; } private Set<CompiledMapping> getMappings(MappingIndexes.IndexTypes indexType, Object key) { Set<CompiledMapping> mappings = getIndex(indexType).get(key); return mappings != null ? mappings : Collections.<CompiledMapping>emptySet(); } private void add(MappingIndexes.IndexTypes indexType, Object key, CompiledMapping mapping) { if (key != null) { Set<CompiledMapping> mappings = getIndex(indexType).get(key); if (mappings == null) getIndex(indexType).put(key, mappings = new HashSet<CompiledMapping>()); mappings.add(mapping); } } private CompiledMapping add(CompiledMapping mapping) { add(IndexTypes.MAPPING_TYPE, mapping.mappingType, mapping); add(IndexTypes.CONTEXT, mapping.context, mapping); add(IndexTypes.ED, mapping.ed, mapping); add(IndexTypes.FD, mapping.fd, mapping); add(IndexTypes.NCNAME, mapping.ncname, mapping); return mapping; } private enum IndexTypes { MAPPING_TYPE, CONTEXT, ED, FD, NCNAME } public static class CompiledMapping { public static final CompiledMapping NULL = new CompiledMapping() { public boolean isNull() { return true; } }; public EntityDescriptor<?> mappingType; public EntityDescriptor<?> context; public EntityDescriptor<?> ed; public FeatureDescriptor fd; public String ncname; protected CompiledMapping() { } protected CompiledMapping(EntityDescriptor<?> mappingType, EntityDescriptor<?> context, EntityDescriptor<?> ed, FeatureDescriptor fd, String ncname) { this.mappingType = mappingType; this.context = context; this.ed = ed; this.fd = fd; this.ncname = ncname; } protected CompiledMapping(Mapping mapping) { this.mappingType = mapping.wGetEntityDescriptor(); mapping.accept(new MappingIdentityDefaultVisitor() { @Override public void visit(ContentMapping entity) { context = parseEntityDescriptor(entity.getContextEntityType().getValue()); fd = parseFeatureDescriptor(entity.getFeatureType().getValue()); ed = parseEntityDescriptor(entity.getEntityType().getValue()); } @Override public void visit(MixedStructuralMapping entity) { context = parseEntityDescriptor(entity.getContextEntityType().getValue()); fd = parseFeatureDescriptor(entity.getFeatureType().getValue()); ed = parseEntityDescriptor(entity.getEntityType().getValue()); } @Override public void visit(AnyMapping entity) { context = parseEntityDescriptor(entity.getContextEntityType().getValue()); fd = parseFeatureDescriptor(entity.getFeatureType().getValue()); ed = parseEntityDescriptor(entity.getEntityType().getValue()); //TODO test and modularize if (SchemaUtils.hasAnyTypeEntityName(ed)) ed.getEntityDescriptorEnum().setAssignableFromAll(true, ed.getOrdinal()); } @Override public void visit(TypeMapping entity) { context = parseEntityDescriptor(entity.getContextEntityType().getValue()); ncname = entity.getName().getValue(); fd = parseFeatureDescriptor(entity.getFeatureType().getValue()); ed = parseEntityDescriptor(entity.getEntityType().getValue()); //TODO test and modularize if (!ed.getLanguageKit().equals(context.getLanguageKit())) context.getEntityDescriptorEnum().setAssignableFromAll(true, context.getEntityDescriptor(fd).getOrdinal()); } @Override public void visit(RootMapping entity) { ncname = entity.getName().getValue(); ed = parseEntityDescriptor(entity.getEntityType().getValue()); } }); } public boolean isNull() { return false; } } }