/** * 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.models.util; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.whole.lang.iterators.AbstractPatternFilterIterator; import org.whole.lang.iterators.IteratorFactory; import org.whole.lang.iterators.ScannerIterator; import org.whole.lang.matchers.Matcher; import org.whole.lang.model.IEntity; import org.whole.lang.models.factories.ModelsEntityFactory; import org.whole.lang.models.model.CompositeEntity; import org.whole.lang.models.model.EntityModifierEnum; import org.whole.lang.models.model.Feature; import org.whole.lang.models.model.FeatureModifierEnum; import org.whole.lang.models.model.Features; import org.whole.lang.models.model.Model; import org.whole.lang.models.model.ModelDeclaration; import org.whole.lang.models.model.ModelDeclarations; import org.whole.lang.models.model.SimpleEntity; import org.whole.lang.models.model.SimpleName; import org.whole.lang.models.model.Type; import org.whole.lang.models.model.Types; import org.whole.lang.models.reflect.ModelsEntityDescriptorEnum; import org.whole.lang.util.DataTypeUtils; import org.whole.lang.util.EntityUtils; import org.whole.lang.util.FreshNameGenerator; import org.whole.lang.util.StringUtils; /** * @author Riccardo Solmi */ public class ModelInfo { public final Map<String, String> entityNameImplNameMap = new HashMap<String, String>(); public final Map<String, String> featureNameImplNameMap = new HashMap<String, String>(); public final List<String> entityNameList = new ArrayList<String>(); public final List<String> featureNameList = new ArrayList<String>(); public final Set<String> featureNames = new HashSet<String>(); public final Map<String, IEntity> nameEntityMap = new HashMap<String, IEntity>(); public final Set<String> definedTypes = new HashSet<String>(); public final Set<String> referencedTypes = new HashSet<String>(); public final Set<String> undefinedTypes = new HashSet<String>(); public final Set<String> unreferencedTypes = new HashSet<String>(); public final Map<String, Set<String>> superTypes = new HashMap<String, Set<String>>(); //without self public final Map<String, Set<String>> subTypes = new HashMap<String, Set<String>>(); //without self public final Map<String, Set<String>> allSuperTypes = new HashMap<String, Set<String>>(); public final Map<String, Set<String>> allSubTypes = new HashMap<String, Set<String>>(); public final Set<String> markerTypes = new HashSet<String>(); public final Set<String> abstractTypes = new HashSet<String>(); public final Set<String> simpleEntityTypes = new HashSet<String>(); public final Map<String, Set<String>> simpleEntityOrigFeatures = new HashMap<String, Set<String>>(); public final Map<String, Set<String>> simpleEntityFeatures = new HashMap<String, Set<String>>(); public ModelInfo(Model model) { FreshNameGenerator entityNameGen = new FreshNameGenerator(); FreshNameGenerator featureNameGen = new FreshNameGenerator(); ScannerIterator<ModelDeclaration> i = IteratorFactory.<ModelDeclaration>childScannerIterator(); i.reset(model.getDeclarations()); for (ModelDeclaration md : i) { SimpleName simpleName; if (!DataTypeUtils.getDataKind(simpleName = md.getName()).isString()) continue; String entityName = simpleName.wStringValue(); nameEntityMap.put(entityName, md); definedTypes.add(entityName); entityNameList.add(entityName); if (StringUtils.isValidEntityName(entityName)) entityNameGen.putBoundName(entityName); if (md.getModifiers().wContainsValue(EntityModifierEnum._abstract)) abstractTypes.add(entityName); AbstractPatternFilterIterator<Type> i3 = IteratorFactory.<Type>childMatcherIterator() .withPattern(ModelsEntityDescriptorEnum.SimpleName); i3.reset(md.getTypes()); for (Type type : i3) { String typeName = type.wStringValue(); referencedTypes.add(typeName); superTypes(entityName).add(typeName); subTypes(typeName).add(entityName); } if (Matcher.match(ModelsEntityDescriptorEnum.SimpleEntity, md)) { SimpleEntity se = (SimpleEntity) md; simpleEntityTypes.add(entityName); if (se.getFeatures().wIsEmpty()) markerTypes.add(entityName); Set<String> featureNameSet = new HashSet<String>(); ScannerIterator<Feature> i2 = IteratorFactory.<Feature>childScannerIterator(); i2.reset(se.getFeatures()); for (Feature feature : i2) { SimpleName featureName = feature.getName(); if (!Matcher.match(ModelsEntityDescriptorEnum.SimpleName, featureName)) continue; String fName = featureName.wStringValue(); featureNameSet.add(fName); if (featureNames.add(fName)) featureNameList.add(fName); if (StringUtils.isValidFeatureName(fName)) featureNameGen.putBoundName(fName); Type featureType = feature.getType(); if (Matcher.match(ModelsEntityDescriptorEnum.SimpleName, featureType)) referencedTypes.add(featureType.wStringValue()); } simpleEntityOrigFeatures.put(entityName, featureNameSet); simpleEntityFeatures.put(entityName, new HashSet<String>(featureNameSet)); } else if (Matcher.match(ModelsEntityDescriptorEnum.CompositeEntity, md)) { CompositeEntity ce = (CompositeEntity) md; Type componentType = ce.getComponentType(); if (Matcher.match(ModelsEntityDescriptorEnum.SimpleName, componentType)) referencedTypes.add(componentType.wStringValue()); } } undefinedTypes.addAll(referencedTypes); undefinedTypes.removeAll(definedTypes); unreferencedTypes.addAll(definedTypes); unreferencedTypes.removeAll(referencedTypes); for (String entityName : undefinedTypes) { entityNameList.add(entityName); if (StringUtils.isValidEntityName(entityName)) entityNameGen.putBoundName(entityName); } for (String name : entityNameList()) entityNameImplNameMap.put(name, entityNameGen.isBoundOnlyName(name) ? name : entityNameGen.nextFreshName(StringUtils.toEntityName(name))); for (String name : featureNameList()) featureNameImplNameMap.put(name, featureNameGen.isBoundOnlyName(name) ? name : featureNameGen.nextFreshName(StringUtils.toFeatureName(name))); } public List<String> entityNameList() { return entityNameList; } public List<String> featureNameList() { return featureNameList; } public Set<String> entityImplNames(Set<String> names) { Set<String> implNames = new HashSet<String>(names.size()); for (String name : names) implNames.add(entityImplName(name)); return implNames; } public String entityImplName(String name) { return entityNameImplNameMap.get(name); } public String featureImplName(String name) { return featureNameImplNameMap.get(name); } public Set<String> superTypes(String entityName) { Set<String> result = superTypes.get(entityName); if (result == null) superTypes.put(entityName, result = new HashSet<String>()); return result; } public Set<String> subTypes(String entityName) { Set<String> result = subTypes.get(entityName); if (result == null) subTypes.put(entityName, result = new HashSet<String>()); return result; } public Set<String> allSuperTypes(String entityName) { Set<String> allTypes = allSuperTypes.get(entityName); if (allTypes == null) { allSuperTypes.put(entityName, allTypes = new HashSet<String>()); allTypes.add(entityName); List<String> pendingTypes = new ArrayList<String>(allTypes); for (int i=0; i<pendingTypes.size(); i++) { Set<String> newTypes = new HashSet<String>(superTypes(pendingTypes.get(i))); newTypes.removeAll(allTypes); allTypes.addAll(newTypes); pendingTypes.addAll(newTypes); } } return allTypes; } public Set<String> allSubTypes(String entityName) { Set<String> allTypes = allSubTypes.get(entityName); if (allTypes == null) { allSubTypes.put(entityName, allTypes = new HashSet<String>()); allTypes.add(entityName); List<String> pendingTypes = new ArrayList<String>(allTypes); for (int i=0; i<pendingTypes.size(); i++) { Set<String> newTypes = new HashSet<String>(subTypes(pendingTypes.get(i))); newTypes.removeAll(allTypes); allTypes.addAll(newTypes); pendingTypes.addAll(newTypes); } allTypes.remove(entityName); } return allTypes; } public Set<String> allConcreteSubTypes(String entityName) { Set<String> allImplementations = new HashSet<String>(allSubTypes(entityName)); allImplementations.removeAll(abstractTypes); return allImplementations; } public boolean hasMarkerInterface(String entityName) { return referencedTypes.contains(entityName); } public boolean isNotInherited(String entityName, String featureName) { return simpleEntityOrigFeatures.get(entityName) == null || simpleEntityOrigFeatures.get(entityName).contains(featureName); } public Set<String> simpleEntityOrigFeatures(String name) { return simpleEntityOrigFeatures.get(name); } public Set<String> simpleEntityFeatures(String name) { return simpleEntityFeatures.get(name); } public void addUndeclaredTypes(Model model) { ModelDeclarations decls = model.getDeclarations(); ModelsEntityFactory lf = ModelsEntityFactory.instance; for (String name : undefinedTypes) { decls.wAdd(lf.createSimpleEntity( lf.createEntityModifiers(lf.createEntityModifier(EntityModifierEnum._abstract)), lf.createSimpleName(name), lf.createTypes(), lf.createFeatures())); } markerTypes.addAll(undefinedTypes); abstractTypes.addAll(undefinedTypes); undefinedTypes.clear(); } public void addInheritedFeatures(Model model) { for (String entityName : simpleEntityTypes) { SimpleEntity e = (SimpleEntity) nameEntityMap.get(entityName); addInheritedFeatures(e, e.getTypes(), new HashSet<String>(simpleEntityTypes), simpleEntityFeatures); } } protected void addInheritedFeatures(SimpleEntity entity, Types types, Set<String> entityTypes, Map<String, Set<String>> entityFeatures) { ScannerIterator<IEntity> i = IteratorFactory.childReverseScannerIterator(); i.reset(types); for (IEntity type : i) { String typeName = type.wStringValue(); entityTypes.remove(typeName); SimpleEntity declaration = (SimpleEntity) nameEntityMap.get(typeName); if (declaration != null) { ScannerIterator<Feature> i2 = IteratorFactory.<Feature>childReverseScannerIterator(); i2.reset(declaration.getFeatures()); for (Feature feature : i2) { if (entityFeatures.get(entity.getName().wStringValue()).add(feature.getName().wStringValue())) entity.getFeatures().wAdd(0, EntityUtils.clone(feature)); } addInheritedFeatures(entity, declaration.getTypes(), entityTypes, entityFeatures); } } } public void sortFeatures(Model model) { for (String entityName : simpleEntityTypes) { SimpleEntity e = (SimpleEntity) nameEntityMap.get(entityName); Features features = e.getFeatures(); Collections.sort(features, new Comparator<Feature>() { public int compare(Feature f1, Feature f2) { boolean f1IsReference = f1.getModifiers().wContainsValue(FeatureModifierEnum.reference); boolean f2IsReference = f2.getModifiers().wContainsValue(FeatureModifierEnum.reference); if (f2IsReference) return f1IsReference ? 0 : -1; else return !f1IsReference ? 0 : +1; } }); } } }