/**
* 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.reflect;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import org.junit.BeforeClass;
import org.junit.Test;
import org.whole.lang.codebase.ClasspathPersistenceProvider;
import org.whole.lang.commons.reflect.CommonsFeatureDescriptorEnum;
import org.whole.lang.factories.GenericEntityFactory;
import org.whole.lang.factories.IEntityFactory;
import org.whole.lang.grammars.factories.GrammarsEntityFactory;
import org.whole.lang.matchers.Matcher;
import org.whole.lang.model.IEntity;
import org.whole.lang.models.model.Model;
import org.whole.lang.operations.InterpreterOperation;
import org.whole.lang.operations.NormalizerOperation;
import org.whole.lang.queries.factories.QueriesEntityFactory;
import org.whole.lang.xml.codebase.XmlBuilderPersistenceKit;
/**
* @author Riccardo Solmi
*/
public class DynamicModelDefinitionTest {
@BeforeClass
public static void deployWholePlatform() {
ReflectionFactory.deployWholePlatform();
}
@Test
public void testFeatureDescriptorEnumDefinition() {
DynamicLanguageKit lk = new DynamicLanguageKit();
lk.setURI("http://lang.whole.org/DynamicImpl");
lk.setNamespace("org.whole.lang.reflect");
lk.setName("DynamicImp");
FeatureDescriptorEnum fds = lk.getFeatureDescriptorEnum();
fds.addFeatureDescriptors("one", "two", "tree");
assertEquals(3, fds.size());
fds.addFeatureDescriptor("four");
assertEquals(4, fds.size());
fds.addFeatureDescriptor("one"); //duplicate
assertEquals(4, fds.size());
fds.addFeatureDescriptors("one", "five", "six", "five"); //two duplicates
assertEquals(6, fds.size());
}
@Test
public void testEntityDescriptorEnumDefinition() {
DynamicLanguageKit lk = new DynamicLanguageKit();
lk.setURI("http://lang.whole.org/DynamicImpl");
lk.setNamespace("org.whole.lang.reflect");
lk.setName("DynamicImp");
EntityDescriptorEnum eds = lk.getEntityDescriptorEnum();
FeatureDescriptorEnum fds = lk.getFeatureDescriptorEnum();
EntityDescriptor<?> e1 = eds.addSimpleEntity("zero", "zero", false);
assertEquals("zero", e1.getName());
assertEquals(0, e1.getOrdinal());
EntityDescriptor<?> e2 = eds.addSimpleEntity("one", "one", false)
.withFeature(fds.addFeatureDescriptor("f1"), e1.getOrdinal());
assertEquals("one", e2.getName());
assertEquals(1, e2.getOrdinal());
EntityDescriptor<?> e3 = eds.addSimpleEntity("two", "two", false)
.withFeature(fds.addFeatureDescriptor("f1"), e2.getOrdinal());
e3.withFeature(fds.addFeatureDescriptor("f2"), e3.getOrdinal());
assertEquals("two", e3.getName());
assertEquals(2, e3.getOrdinal());
EntityDescriptor<?> e4 = eds.addCompositeEntity("list", "list", false, true, false);
e4.withFeature(CommonsFeatureDescriptorEnum.composite_element, e2.getOrdinal());
assertEquals("list", e4.getName());
assertEquals(3, e4.getOrdinal());
assertEquals(CompositeKinds.LIST, e4.getCompositeKind());
EntityDescriptor<?> e5 = eds.addDataEntity("intData", "intData", false, int.class);
assertEquals("intData", e5.getName());
assertEquals(4, e5.getOrdinal());
assertTrue(e5.getDataKind().isInt());
EntityDescriptor<?> e6 = eds.addEnumEntity("enumData", "enumData", "a", "b", "c");
assertEquals("enumData", e6.getName());
assertEquals(5, e6.getOrdinal());
assertTrue(e6.getDataKind().isEnumValue());
assertEquals(3, e6.getDataEnumType().size());
//TODO test map
}
@Test
public void testLanguageKitDefinition() {
DynamicLanguageKit lk = new DynamicLanguageKit();
lk.setURI("http://lang.whole.org/DynamicImpl");
lk.setNamespace("org.whole.lang.reflect");
lk.setName("DynamicImp");
FeatureDescriptorEnum fds = lk.getFeatureDescriptorEnum();
fds.addFeatureDescriptors(
"value", "type", "name", "parameters", "body", "initializer",
"exp", "exp1", "exp2", "condition", "trueBody", "falseBody",
"arguments", "updater");
EntityDescriptorEnum eds = lk.getEntityDescriptorEnum();
final EntityDescriptor<?> ExpressionDesc = eds.addSimpleEntity("Expression", "Expression", true);
final EntityDescriptor<?> StatementDesc = eds.addSimpleEntity("Statement", "Statement", true);
EntityDescriptor<?> bs = eds.addCompositeEntity("BlockStatement", "BlockStatement", false, true, false);
bs.withFeature(CommonsFeatureDescriptorEnum.composite_element, StatementDesc.getOrdinal());
EntityDescriptor<?> ifs = eds.addSimpleEntity("IfStatement", "IfStatement", false)
.withFeature(fds.valueOf("condition"), ExpressionDesc.getOrdinal())
.withFeature(fds.valueOf("trueBody"), StatementDesc.getOrdinal());
EntityDescriptor<?> ifes = eds.addSimpleEntity("IfElseStatement", "IfElseStatement", false)
.withFeature(fds.valueOf("condition"), ExpressionDesc.getOrdinal())
.withFeature(fds.valueOf("trueBody"), StatementDesc.getOrdinal())
.withFeature(fds.valueOf("falseBody"), StatementDesc.getOrdinal());
EntityDescriptor<?> ws = eds.addSimpleEntity("WhileStatement", "WhileStatement", false)
.withFeature(fds.valueOf("condition"), ExpressionDesc.getOrdinal())
.withFeature(fds.valueOf("body"), StatementDesc.getOrdinal());
EntityDescriptor<?> es = eds.addSimpleEntity("ExpressionStatement", "ExpressionStatement", false)
.withFeature(fds.valueOf("exp"), ExpressionDesc.getOrdinal());
StatementDesc.setLanguageSubtypes(true,
bs.getOrdinal(), ifs.getOrdinal(), ifes.getOrdinal(), ws.getOrdinal(), es.getOrdinal());
final EntityDescriptor<?> LiteralDesc = eds.addSimpleEntity("Literal", "Literal", true);
LiteralDesc.setLanguageSubtypes(true,
eds.addDataEntity("BooleanLiteral", "BooleanLiteral", false, Boolean.TYPE).getOrdinal(),
eds.addDataEntity("IntLiteral", "IntLiteral", false, Integer.TYPE).getOrdinal(),
eds.addDataEntity("StringLiteral", "StringLiteral", false, String.class).getOrdinal());
EntityDescriptor<?> ne = eds.addDataEntity("Name", "Name", false, String.class);
eds.addSimpleEntity("AssignmentExpression", "AssignmentExpression", false)
.withFeature(fds.valueOf("name"), ne.getOrdinal())
.withFeature(fds.valueOf("exp"), ExpressionDesc.getOrdinal());
for (String edName : new String[] {
"And", "Or",
"Addition", "Division", "Multiplication", "Remainder", "Subtraction",
"Equals", "GreaterOrEquals", "GreaterThan", "LessOrEquals", "LessThan", "NotEquals"}) {
eds.addSimpleEntity(edName, edName, false)
.withFeature(fds.valueOf("exp1"), ExpressionDesc.getOrdinal())
.withFeature(fds.valueOf("exp1"), ExpressionDesc.getOrdinal());
}
//TODO configure entity registry
ReflectionFactory.deploy(DynamicLanguageKit.getDeployer(lk));
assertEquals(lk, ReflectionFactory.getLanguageKit(lk.getURI()));
IEntityFactory ef = GenericEntityFactory.instance;
IEntity p = ef.create(
eds.valueOf("WhileStatement"),
ef.create(eds.valueOf("GreaterThan"),
ef.create(eds.valueOf("Name"), "n"),
ef.create(eds.valueOf("IntLiteral"), 0)),
ef.create(eds.valueOf("ExpressionStatement"),
ef.create(eds.valueOf("AssignmentExpression"),
ef.create(eds.valueOf("Name"), "n"),
ef.create(eds.valueOf("Subtraction"),
ef.create(eds.valueOf("Name"), "n"),
ef.create(eds.valueOf("IntLiteral"), 1)))));
assertEquals(lk, p.wGetLanguageKit());
}
@Test
public void testTupleDefinition() {
DynamicLanguageKit lk = new DynamicLanguageKit();
lk.setURI("http://lang.whole.org/QueriesTupleResultLanguage");
lk.setNamespace("org.whole.lang.reflect");
lk.setName("QueriesTupleResultLanguage");
EntityDescriptorEnum eds = lk.getEntityDescriptorEnum();
EntityDescriptor<?> any = eds.addSimpleEntity("Any", "Any", true);
EntityDescriptor<?> gtd = eds.addCompositeEntity("GenericTuple", "GenericTuple", false, true, false);
gtd.withFeature(CommonsFeatureDescriptorEnum.composite_element, any.getOrdinal());
eds.setAssignableFromAll(true, any.getOrdinal());
ReflectionFactory.deploy(DynamicLanguageKit.getDeployer(lk));
assertEquals(lk, ReflectionFactory.getLanguageKit(lk.getURI()));
IEntityFactory ef = GenericEntityFactory.instance;
IEntity p = ef.create(eds.valueOf("GenericTuple"));
IEntity[] e = new IEntity[2];
p.wAdd(e[0] = QueriesEntityFactory.instance.createSelfStep());
p.wAdd(e[1] = GrammarsEntityFactory.instance.createNonTerminal("myNt"));
assertEquals(2, p.wSize());
assertSame(e[0], p.wGet(0));
assertSame(e[1], p.wGet(1));
}
@Test
public void testModelsInterpreter() {
Model model;
try {
model = (Model) XmlBuilderPersistenceKit.instance().readModel(
new ClasspathPersistenceProvider("org/whole/lang/queries/QueriesModel.xwl"));
} catch (Exception e) {
throw new IllegalStateException(e);
}
String URI = "http://my/uri/for/queries/lang";
model.getUri().setValue(URI);
ILanguageKit qlk = ReflectionFactory.getLanguageKit("http://lang.whole.org/Queries");
EntityDescriptorEnum qedenum = qlk.getEntityDescriptorEnum();
FeatureDescriptorEnum qfdenum = qlk.getFeatureDescriptorEnum();
InterpreterOperation.interpret(model);
ILanguageKit lk = ReflectionFactory.getLanguageKit(URI);
assertNotNull(lk);
assertNotSame(qlk, lk);
assertNotNull(lk.getMetaModelTemplate());
IEntity metaModel = lk.getMetaModel();
IEntity normalizedModel = NormalizerOperation.normalize(model);
assertTrue(Matcher.match(normalizedModel, metaModel));
metaModel = lk.getMetaModelTemplate().create();
assertTrue(Matcher.match(normalizedModel, metaModel));
EntityDescriptorEnum edenum = lk.getEntityDescriptorEnum();
FeatureDescriptorEnum fdenum = lk.getFeatureDescriptorEnum();
assertFalse(qfdenum.equals(fdenum));
assertEquals(qfdenum.size(), fdenum.size());
for (FeatureDescriptor qfd : qfdenum) {
assertEquals(qfd.getOrdinal(), fdenum.valueOf(qfd.getName()).getOrdinal());
}
assertFalse(qedenum.equals(edenum));
assertEquals(qedenum.size(), edenum.size());
for (EntityDescriptor<?> qed : qedenum) {
EntityDescriptor<?> ed = edenum.valueOf(qed.getName());
assertEquals(qed.getOrdinal(), ed.getOrdinal());
assertEquals(qed.getEntityKind(), ed.getEntityKind());
assertEquals(qed.isAbstract(), ed.isAbstract());
assertEquals(qed.isRelationship(), ed.isRelationship());
switch (qed.getEntityKind()) {
case SIMPLE:
assertEquals(qed.featureSize(), ed.featureSize());
for (int i=0, size=qed.featureSize(); i<size; i++) {
FeatureDescriptor qfd = qed.getEntityFeatureDescriptor(i);
FeatureDescriptor fd = ed.getEntityFeatureDescriptor(i);
assertEquals(qfd.getName(), fd.getName());
assertEquals(qfd.getImplName(), fd.getImplName());
assertEquals(qfd.getOrdinal(), fd.getOrdinal());
assertEquals(qfd.isDerived(), fd.isDerived());
assertEquals(qfd.isId(), fd.isId());
assertEquals(qfd.isOptional(), fd.isOptional());
assertEquals(qfd.isReference(), fd.isReference());
assertEquals(qfd.isShared(), fd.isShared());
assertEquals(qfd.isToMany(), fd.isToMany());
if (qfd.getOppositeFeatureDescriptor() != null)
assertEquals(
qfd.getOppositeFeatureDescriptor().getName(),
fd.getOppositeFeatureDescriptor().getName());
}
break;
case COMPOSITE:
assertEquals(qed.getCompositeKind(), ed.getCompositeKind());
FeatureDescriptor qfd = qed.getEntityFeatureDescriptor(0);
FeatureDescriptor fd = ed.getEntityFeatureDescriptor(0);
assertEquals(qfd.isDerived(), fd.isDerived());
assertEquals(qfd.isReference(), fd.isReference());
assertEquals(qfd.isShared(), fd.isShared());
break;
case DATA:
assertEquals(qed.getDataKind(), ed.getDataKind());
if (qed.getDataKind().isEnumValue()) {
assertEquals(qed.getDataEnumType().size(), ed.getDataEnumType().size());
for (int i=0; i<qed.getDataEnumType().size(); i++)
assertEquals(qed.getDataEnumType().valueOf(i).getName(), ed.getDataEnumType().valueOf(i).getName());
} else
assertEquals(qed.getDataType(), ed.getDataType());
break;
}
}
}
}