/** * 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.visitors; import org.whole.lang.bindings.BindingManagerFactory; import org.whole.lang.commons.reflect.CommonsFeatureDescriptorEnum; import org.whole.lang.iterators.IEntityIterator; import org.whole.lang.iterators.IteratorFactory; import org.whole.lang.matchers.Matcher; import org.whole.lang.models.model.AnyType; import org.whole.lang.models.model.ComponentModifier; import org.whole.lang.models.model.ComponentModifierEnum; import org.whole.lang.models.model.CompositeEntity; import org.whole.lang.models.model.DataEntity; import org.whole.lang.models.model.EntityModifierEnum; import org.whole.lang.models.model.EntityType; import org.whole.lang.models.model.EnumEntity; import org.whole.lang.models.model.EnumValues; import org.whole.lang.models.model.Feature; import org.whole.lang.models.model.FeatureModifier; import org.whole.lang.models.model.FeatureModifierEnum; import org.whole.lang.models.model.Features; import org.whole.lang.models.model.IModelsEntity; import org.whole.lang.models.model.Model; import org.whole.lang.models.model.SimpleEntity; import org.whole.lang.models.model.SimpleName; import org.whole.lang.models.model.SubtypesOf; import org.whole.lang.models.model.SupertypesOf; import org.whole.lang.models.model.TypeAliasOf; import org.whole.lang.models.model.Types; import org.whole.lang.models.reflect.ModelsEntityDescriptorEnum; import org.whole.lang.models.util.ModelInfo; import org.whole.lang.reflect.DynamicLanguageKit; import org.whole.lang.reflect.EntityDescriptor; import org.whole.lang.reflect.EntityDescriptorEnum; import org.whole.lang.reflect.FeatureDescriptor; import org.whole.lang.reflect.FeatureDescriptorEnum; import org.whole.lang.reflect.ReflectionFactory; import org.whole.lang.util.EntityUtils; import org.whole.lang.util.StringUtils; import org.whole.lang.visitors.VisitException; /** * @author Riccardo Solmi */ public class ModelsInterpreterVisitor extends ModelsIdentityDefaultVisitor { private EntityDescriptorEnum entityDescriptorEnum; private FeatureDescriptorEnum featureDescriptorEnum; private ModelInfo modelInfo; protected ClassLoader getClassLoader() { return ReflectionFactory.getClassLoader(getBindings()); } @Override public void visit(IModelsEntity entity) { Model m = Matcher.findAncestor(ModelsEntityDescriptorEnum.Model, entity); if (m != null) visit(m); throw new VisitException(); } @Override public void visit(Model entity) { boolean hasArgLanguageKit = getBindings().wIsSet("languageKit"); DynamicLanguageKit argLanguageKit = hasArgLanguageKit ? (DynamicLanguageKit) getBindings().wGetValue("languageKit") : null; boolean useArgLanguageKit = hasArgLanguageKit && argLanguageKit.getURI().equals(entity.getUri().getValue()); DynamicLanguageKit languageKit; if (useArgLanguageKit) languageKit = argLanguageKit; else { languageKit = new DynamicLanguageKit(); languageKit.setURI(entity.getUri().getValue()); languageKit.setNamespace(entity.getNamespace().getValue()); languageKit.setName(entity.getName().getValue()); languageKit.setVersion(EntityUtils.isResolver(entity.getVersion()) ? "" : entity.getVersion().getValue()); } entity = EntityUtils.cloneIfParented(entity); languageKit.setEntity(entity); configureLanguageKit(languageKit, entity); ReflectionFactory.updatePersistenceAndEditorKits(languageKit); if (!useArgLanguageKit) { ReflectionFactory.deploy(DynamicLanguageKit.getDeployer(languageKit)); if (hasArgLanguageKit) getBindings().wSetValue("languageKit", argLanguageKit); } setResult(BindingManagerFactory.instance.createValue(languageKit)); } public void configureLanguageKit(DynamicLanguageKit languageKit, Model model) { modelInfo = new ModelInfo(model); modelInfo.addInheritedFeatures(model); modelInfo.addUndeclaredTypes(model); modelInfo.sortFeatures(model); entityDescriptorEnum = languageKit.getEntityDescriptorEnum(); featureDescriptorEnum = languageKit.getFeatureDescriptorEnum(); model.getDeclarations().accept(new EntityDescriptorDefinitionVisitor()); model.getDeclarations().accept(new EntityDescriptorCompletionVisitor()); model.getTypeRelations().accept(new TypeRelationsVisitor()); } private class TypeRelationsVisitor extends ModelsTraverseAllChildrenVisitor { protected String foreignEdUri; protected int[] edOrdinals; protected int edOrdinal; @Override public void visit(SupertypesOf entity) { super.visit(entity); if (foreignEdUri != null) entityDescriptorEnum.setAssignableFromForeignType(true, foreignEdUri, edOrdinals); else entityDescriptorEnum.setAssignableFromAll(true, edOrdinals); } @Override public void visit(SubtypesOf entity) { super.visit(entity); if (foreignEdUri != null) entityDescriptorEnum.setAssignableToForeignType(true, foreignEdUri, edOrdinals); else entityDescriptorEnum.setAssignableToAll(true, edOrdinals); } @Override public void visit(TypeAliasOf entity) { super.visit(entity); entityDescriptorEnum.setAliasOf(true, foreignEdUri, edOrdinal); } @Override public void visit(AnyType entity) { foreignEdUri = null; } @Override public void visit(EntityType entity) { foreignEdUri = entity.getValue(); } @Override public void visit(Types entity) { int size = entity.size(); edOrdinals = new int[size]; for (int i=0; i<size; i++) { entity.get(i).accept(TypeRelationsVisitor.this); edOrdinals[i] = edOrdinal; } } @Override public void visit(SimpleName entity) { edOrdinal = entityDescriptorEnum.valueOf(entity.getValue()).getOrdinal(); } } private class EntityDescriptorDefinitionVisitor extends ModelsTraverseAllChildrenVisitor { @Override public void visit(DataEntity entity) { String name = entity.getName().wStringValue(); String dataTypeName = entity.getDataType().wStringValue(); Class<?> dataType; if (StringUtils.isPrimitiveOrString(dataTypeName)) dataType = StringUtils.primitiveOrStringClass(dataTypeName); else try { dataType = Class.forName(StringUtils.isAmbiguous(dataTypeName) ? "java.lang."+ dataTypeName : dataTypeName, true, getClassLoader()); } catch (ClassNotFoundException e) { throw new IllegalArgumentException("Cannot find class: "+dataTypeName, e); } org.whole.lang.models.model.EntityModifiers modifiers = entity.getModifiers(); entityDescriptorEnum.addDataEntity(name, modelInfo.entityImplName(name), modifiers.wContainsValue(EntityModifierEnum.relationship), dataType); } @Override public void visit(EnumEntity entity) { String name = entity.getName().wStringValue(); EnumValues evalues = entity.getValues(); int evaluesSize = evalues.wSize(); String[] values = new String[evaluesSize]; for (int i=0; i<evaluesSize; i++) values[i] = evalues.wGet(i).wStringValue(); entityDescriptorEnum.addEnumEntity(name, modelInfo.entityImplName(name), values); } @Override public void visit(CompositeEntity entity) { String name = entity.getName().wStringValue(); boolean isOrdered = false, isUnique = false; IEntityIterator<ComponentModifier> i = IteratorFactory.<ComponentModifier>childIterator(); i.reset(entity.getComponentModifiers()); for (ComponentModifier modifier : i) switch (modifier.getValue().getOrdinal()) { case ComponentModifierEnum.ordered_ord: isOrdered = true; break; case ComponentModifierEnum.unique_ord: isUnique = true; break; } org.whole.lang.models.model.EntityModifiers modifiers = entity.getModifiers(); entityDescriptorEnum.addCompositeEntity(name, modelInfo.entityImplName(name), modifiers.wContainsValue(EntityModifierEnum.relationship), isOrdered, isUnique); } @Override public void visit(SimpleEntity entity) { String name = entity.getName().wStringValue(); org.whole.lang.models.model.EntityModifiers modifiers = entity.getModifiers(); entityDescriptorEnum.addSimpleEntity(name, modelInfo.entityImplName(name), modifiers.wContainsValue(EntityModifierEnum._abstract)); } } private class EntityDescriptorCompletionVisitor extends ModelsTraverseAllChildrenVisitor { @Override public void visit(DataEntity entity) { } @Override public void visit(EnumEntity entity) { } @Override public void visit(CompositeEntity entity) { String name = entity.getName().wStringValue(); String componentName = entity.getComponentType().wStringValue(); boolean isReference = false, isDerived = false, isShared = false; IEntityIterator<ComponentModifier> i = IteratorFactory.<ComponentModifier>childIterator(); i.reset(entity.getComponentModifiers()); for (ComponentModifier modifier : i) switch (modifier.getValue().getOrdinal()) { case ComponentModifierEnum.reference_ord: isReference = true; break; case ComponentModifierEnum.derived_ord: isDerived = true; break; case ComponentModifierEnum.shared_ord: isShared = true; break; } entityDescriptorEnum.valueOf(name).withFeature( CommonsFeatureDescriptorEnum.composite_element, entityDescriptorEnum.valueOf(componentName).getOrdinal(), false, false, isReference, isDerived, isShared); } @Override public void visit(SimpleEntity entity) { String name = entity.getName().wStringValue(); Features features = entity.getFeatures(); int featureNumber = features.wSize(); EntityDescriptor<?> ed = entityDescriptorEnum.valueOf(name); for (int i=0; i<featureNumber; i++) { Feature feature = features.get(i); String featureName = feature.getName().getValue(); FeatureDescriptor fd = featureDescriptorEnum.addFeatureDescriptor( featureName, modelInfo.featureImplName(featureName)); FeatureDescriptor oppositeFd = null; String oppositeFeatureName = EntityUtils.safeStringValue(feature.getOppositeName(), null); if (oppositeFeatureName != null) oppositeFd = featureDescriptorEnum.addFeatureDescriptor( oppositeFeatureName, modelInfo.featureImplName(oppositeFeatureName)); boolean isOptional = false, isId = false, isReference = false, isDerived = false, isShared = false; IEntityIterator<FeatureModifier> i2 = IteratorFactory.<FeatureModifier>childIterator(); i2.reset(feature.getModifiers()); for (FeatureModifier modifier : i2) switch (modifier.getValue().getOrdinal()) { case FeatureModifierEnum.optional_ord: isOptional = true; break; case FeatureModifierEnum.id_ord: isId = true; break; case FeatureModifierEnum.reference_ord: isReference = true; break; case FeatureModifierEnum.derived_ord: isDerived = true; break; case FeatureModifierEnum.shared_ord: isShared = true; break; } ed.withFeature(fd, entityDescriptorEnum.valueOf(feature.getType().wStringValue()).getOrdinal(), oppositeFd, isOptional, isId, isReference, isDerived, isShared); } for (String ename : modelInfo.allSubTypes(name)) ed.setLanguageSubtypes(true, entityDescriptorEnum.valueOf(ename).getOrdinal()); } } }