package com.sap.ide.cts.editor.ocliatests; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.util.HashSet; import java.util.Set; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.eclipse.emf.common.util.URI; import org.junit.Before; import org.junit.Test; import behavioral.events.EventFilter; import com.sap.ap.metamodel.utils.MetamodelUtils; import com.sap.furcas.metamodel.TCS.ConcreteSyntax; import com.sap.furcas.test.base.StandaloneConnectionBasedTest; import com.sap.furcas.test.util.TcsTestHelper; import data.classes.Association; import data.classes.AssociationEnd; import data.classes.ClassTypeDefinition; import data.classes.MethodSignature; import data.classes.Parameter; import data.classes.SapClass; import data.classes.TypeAdapter; import dataaccess.expressions.MethodCallExpression; import dataaccess.expressions.ObjectCreationExpression; import dataaccess.expressions.VariableExpression; import dataaccess.expressions.literals.ObjectLiteral; import dataaccess.expressions.literals.StringLiteral; public class OclIaTest extends StandaloneConnectionBasedTest { @Before public void initParsingHandlerAndSetupInstanceScopeAnalysis() { // create tcs Syntax ConcreteSyntax tcsSyntax = TcsTestHelper.createTcsSyntaxMappingOnConnection(connection); assertNotNull(tcsSyntax); } @Test public void testLongRunningNavigationPathConstruction() throws OclManagerException { final OclExpressionRegistration registration = MetamodelUtils.createOclExpression(connection, "testLongRunningNavigationPathConstruction", "'.'.concat(self.oclAsType(data::classes::AssociationEnd).name)", AssociationEnd.CLASS_DESCRIPTOR); final AssociationEnd ae = connection.createElement(AssociationEnd.CLASS_DESCRIPTOR); EventFilter eventFilter = registration.getEventFilter(/* notifyNewContextElement */ false); final boolean[] ok = new boolean[1]; ChangeListener listener = new ChangeListener() { @Override public void notify(ChangeEvent event) { Set<URI> affectedElements = registration.getAffectedModelElements((ModelChangeEvent) event, connection); ok[0] = affectedElements.size() == 1 && affectedElements.contains(ae.get___Mri()); } }; connection.getEventRegistry().registerListener(listener, eventFilter); ae.setName("newAeName"); try { assertTrue(ok[0]); } finally { connection.getEventRegistry().deregister(listener); } } /** * self.ownerTypedElement.oclAsType(MethodCallExpression).methodSignature.output.lowerMultiplicity * self.ownerTypedElement.oclAsType(MethodCallExpression).object.getType().lowerMultiplicity */ @Test public void testLowerMultiplicityPropagationForMethodCallOnParameterUsage() throws OclManagerException { final OclExpressionRegistration registration = MetamodelUtils.createOclExpression(connection, "testLowerMultiplicityPropagationForMethodCallOnParameterUsage", "self.ownerTypedElement.oclAsType(MethodCallExpression).methodSignature.output.lowerMultiplicity * "+ "self.ownerTypedElement.oclAsType(MethodCallExpression).object.getType().lowerMultiplicity", ClassTypeDefinition.CLASS_DESCRIPTOR); // construct something like "abc".length(), then change multiplicity of "abc" from 1..1 to 0..1 MethodSignature length = connection.createElement(MethodSignature.CLASS_DESCRIPTOR); length.setName("length"); SapClass numberClass = connection.createElement(SapClass.CLASS_DESCRIPTOR); numberClass.setName("Number"); ClassTypeDefinition msOutput = MetamodelUtils.createClassTypeDefinitionExactlyOne(connection, numberClass); length.setOutput(msOutput); final ClassTypeDefinition ctd = MetamodelUtils.createClassTypeDefinition(connection, numberClass, 1, 1); final MethodCallExpression mce = connection.createElement(MethodCallExpression.CLASS_DESCRIPTOR); mce.setOwnedTypeDefinition(ctd); mce.setMethodSignature(length); Parameter p = connection.createElement(Parameter.CLASS_DESCRIPTOR); SapClass stringClass = connection.createElement(SapClass.CLASS_DESCRIPTOR); p.setOwnedTypeDefinition(MetamodelUtils.createClassTypeDefinitionExactlyOne(connection, stringClass)); VariableExpression ve = connection.createElement(VariableExpression.CLASS_DESCRIPTOR); ve.setVariable(p); // this should infer the variable expression's multiplicity to that of p mce.setObject(ve); EventFilter eventFilter = registration.getEventFilter(/* notifyNewContextElement */ false); final boolean[] ok = new boolean[1]; ChangeListener listener = new ChangeListener() { @Override public void notify(ChangeEvent event) { Set<URI> affectedElements = registration.getAffectedModelElements((ModelChangeEvent) event, connection); ok[0] = affectedElements.size() == 1 && affectedElements.contains(ctd.get___Mri()); } }; connection.getEventRegistry().registerListener(listener, eventFilter); try { assertEquals(1, ve.getType().getLowerMultiplicity()); p.getOwnedTypeDefinition().setLowerMultiplicity(0); assertEquals(0, ve.getType().getLowerMultiplicity()); assertTrue(ok[0]); } finally { connection.getEventRegistry().deregister(listener); } } /** * self.ownerTypedElement.oclAsType(MethodCallExpression).methodSignature.output.lowerMultiplicity * self.ownerTypedElement.oclAsType(MethodCallExpression).object.getType().lowerMultiplicity */ @Test public void testLowerMultiplicityPropagationForMethodCall() throws OclManagerException { final OclExpressionRegistration registration = MetamodelUtils.createOclExpression(connection, "testLowerMultiplicityPropagationForMethodCall", "self.ownerTypedElement.oclAsType(MethodCallExpression).methodSignature.output.lowerMultiplicity * self.ownerTypedElement.oclAsType(MethodCallExpression).object.getType().lowerMultiplicity", ClassTypeDefinition.CLASS_DESCRIPTOR); // construct something like "abc".length(), then change multiplicity of "abc" from 1..1 to 0..1 MethodSignature length = connection.createElement(MethodSignature.CLASS_DESCRIPTOR); length.setName("length"); SapClass numberClass = connection.createElement(SapClass.CLASS_DESCRIPTOR); numberClass.setName("Number"); ClassTypeDefinition msOutput = MetamodelUtils.createClassTypeDefinitionExactlyOne(connection, numberClass); length.setOutput(msOutput); final ClassTypeDefinition ctd = MetamodelUtils.createClassTypeDefinition(connection, numberClass, 1, 1); final MethodCallExpression mce = connection.createElement(MethodCallExpression.CLASS_DESCRIPTOR); mce.setOwnedTypeDefinition(ctd); mce.setMethodSignature(length); StringLiteral sl = connection.createElement(StringLiteral.CLASS_DESCRIPTOR); sl.setLiteral("abc"); SapClass stringClass = connection.createElement(SapClass.CLASS_DESCRIPTOR); sl.setOwnedTypeDefinition(MetamodelUtils.createClassTypeDefinitionExactlyOne(connection, stringClass)); mce.setObject(sl); EventFilter eventFilter = registration.getEventFilter(/* notifyNewContextElement */ false); final boolean[] ok = new boolean[1]; ChangeListener listener = new ChangeListener() { @Override public void notify(ChangeEvent event) { Set<URI> affectedElements = registration.getAffectedModelElements((ModelChangeEvent) event, connection); ok[0] = affectedElements.size() == 1 && affectedElements.contains(ctd.get___Mri()); } }; connection.getEventRegistry().registerListener(listener, eventFilter); try { sl.getOwnedTypeDefinition().setLowerMultiplicity(0); assertTrue(ok[0]); } finally { connection.getEventRegistry().deregister(listener); } } /** * data::classes::SapClass.allInstances()->select(c | c.name = 'something' */ @Test public void testAnalysisOfRecursiveOperationWithSelf() throws OclManagerException { final OclExpressionRegistration registration = MetamodelUtils.createOclExpression(connection, "testAnalysisOfRecursiveOperationWithSelf", "self.object.getType().getInnermost().oclAsType(data::classes::ClassTypeDefinition).clazz.allSignatures()->select(s | s.name = 'testMethod')", MethodCallExpression.CLASS_DESCRIPTOR); // construct something like "new HumbaClass1().m()" final SapClass cl1 = connection.createElement(SapClass.CLASS_DESCRIPTOR); cl1.setName("HumbaClass1"); MethodSignature ms = connection.createElement(MethodSignature.CLASS_DESCRIPTOR); ms.setName("testMethod"); cl1.getOwnedSignatures().add(ms); final ClassTypeDefinition ctd = MetamodelUtils.createClassTypeDefinition(connection, cl1, 1, 1); ctd.setClazz(null); // do that again later to cause the appropriate event final MethodCallExpression mce = connection.createElement(MethodCallExpression.CLASS_DESCRIPTOR); final ObjectCreationExpression oce = connection.createElement(ObjectCreationExpression.CLASS_DESCRIPTOR); oce.setClassToInstantiate(cl1); oce.setOwnedTypeDefinition(ctd); mce.setObject(oce); EventFilter eventFilter = registration.getEventFilter(/* notifyNewContextElement */ false); final boolean[] ok = new boolean[1]; ChangeListener listener = new ChangeListener() { @Override public void notify(ChangeEvent event) { Set<URI> affectedElements = registration.getAffectedModelElements((ModelChangeEvent) event, connection); ok[0] = affectedElements.size() == 1 && affectedElements.contains(mce.get___Mri()) && !affectedElements.contains(ctd.get___Mri()); } }; connection.getEventRegistry().registerListener(listener, eventFilter); try { ctd.setClazz(cl1); assertTrue(ok[0]); } finally { connection.getEventRegistry().deregister(listener); } } /** * data::classes::SapClass.allInstances()->select(c | c.name = 'something' */ @Test public void testAllInstancesSelectClassName() throws OclManagerException { final OclExpressionRegistration registration = MetamodelUtils.createOclExpression(connection, "testAllInstancesSelectClassName", "data::classes::SapClass.allInstances()->select(c | c.name = 'HumbaClass2')", ClassTypeDefinition.CLASS_DESCRIPTOR); final SapClass cl1 = connection.createElement(SapClass.CLASS_DESCRIPTOR); cl1.setName("HumbaClass1"); final ClassTypeDefinition ctd = connection.createElement(ClassTypeDefinition.CLASS_DESCRIPTOR); EventFilter eventFilter = registration.getEventFilter(/* notifyNewContextElement */ false); final boolean[] ok = new boolean[1]; ChangeListener listener = new ChangeListener() { @Override public void notify(ChangeEvent event) { Set<URI> affectedElements = registration.getAffectedModelElements((ModelChangeEvent) event, connection); ok[0] = affectedElements.size() > 0 && affectedElements.contains(ctd.get___Mri()) && !affectedElements.contains(cl1.get___Mri()); } }; connection.getEventRegistry().registerListener(listener, eventFilter); try { cl1.setName("HumbaClass2"); assertTrue(ok[0]); } finally { connection.getEventRegistry().deregister(listener); } } @Test public void testVerySimpleTracerBasedInstanceScopeAnalysisWithNewClassScopeAnalysis() throws OclManagerException { final OclExpressionRegistration registration = MetamodelUtils.createOclExpression( connection, "testVerySimpleTracerBasedInstanceScopeAnalysisWithNewClassScopeAnalysis", "self.oclAsType(data::classes::SapClass).name", SapClass.CLASS_DESCRIPTOR); final SapClass cl1 = connection.createElement(SapClass.CLASS_DESCRIPTOR); cl1.setName("HumbaClass1"); EventFilter eventFilter = registration.getEventFilter(false); final boolean[] ok = new boolean[1]; ChangeListener listener = new ChangeListener() { @Override public void notify(ChangeEvent event) { Set<URI> affectedElements = registration.getAffectedModelElements((ModelChangeEvent) event, connection); ok[0] = affectedElements.size() == 1 && affectedElements.iterator().next().getMofId().equals(cl1.refMofId()); } }; connection.getEventRegistry().registerListener(listener, eventFilter); try { cl1.setName("ChangedHumba1"); assertTrue(ok[0]); } finally { connection.getEventRegistry().deregister(listener); } } @Test public void testInstanceScopeAnalysisForRecursiveOperation() throws OclManagerException { final OclExpressionRegistration registration = MetamodelUtils.createOclExpression(connection, "testInstanceScopeAnalysisForRecursiveOperation", "self.adapters->forAll(a | self.conformsTo(a.to))", SapClass.CLASS_DESCRIPTOR); final SapClass cl1 = connection.createElement(SapClass.CLASS_DESCRIPTOR); cl1.setName("HumbaClass1"); SapClass cl2 = connection.createElement(SapClass.CLASS_DESCRIPTOR); cl2.setName("HumbaClass2"); TypeAdapter adapter = connection.createElement(TypeAdapter.CLASS_DESCRIPTOR); adapter.setName("HumbaClass1_to_HumbaClass2_Adapter"); EventFilter eventFilter = registration.getEventFilter(false); final boolean[] ok = new boolean[1]; ChangeListener listener = new ChangeListener() { @Override public void notify(ChangeEvent event) { Set<URI> affectedElements = registration.getAffectedModelElements((ModelChangeEvent) event, connection); ok[0] = affectedElements.size() == 1 && affectedElements.iterator().next().getMofId().equals(cl1.refMofId()); } }; connection.getEventRegistry().registerListener(listener, eventFilter); try { adapter.setAdapted(cl1); adapter.setTo(cl2); assertTrue(ok[0]); } finally { connection.getEventRegistry().deregister(listener); } } @Test public void testVerySimpleInstanceScopeAnalysisWithTupleUsingSelf() throws OclManagerException { final OclExpressionRegistration registration = MetamodelUtils.createOclExpression(connection, "testVerySimpleInstanceScopeAnalysisWithTupleUsingSelf", "Tuple{cls=self}.cls.name", SapClass.CLASS_DESCRIPTOR); final SapClass cl1 = connection.createElement(SapClass.CLASS_DESCRIPTOR); cl1.setName("HumbaClass1"); EventFilter eventFilter = registration.getEventFilter(false); final boolean[] ok = new boolean[1]; ChangeListener listener = new ChangeListener() { @Override public void notify(ChangeEvent event) { Set<URI> affectedElements = registration.getAffectedModelElements((ModelChangeEvent) event, connection); ok[0] = affectedElements.size() == 1 && affectedElements.iterator().next().getMofId().equals(cl1.refMofId()); } }; connection.getEventRegistry().registerListener(listener, eventFilter); try { cl1.setName("ChangedHumba1"); assertTrue(ok[0]); } finally { connection.getEventRegistry().deregister(listener); } } @Test public void testVerySimpleInstanceScopeAnalysisWithTuple() throws OclManagerException { final OclExpressionRegistration registration = MetamodelUtils.createOclExpression(connection, "testVerySimpleInstanceScopeAnalysisWithTuple", "Tuple{name=self.name}.name", SapClass.CLASS_DESCRIPTOR); final SapClass cl1 = connection.createElement(SapClass.CLASS_DESCRIPTOR); cl1.setName("HumbaClass1"); EventFilter eventFilter = registration.getEventFilter(false); final boolean[] ok = new boolean[1]; ChangeListener listener = new ChangeListener() { @Override public void notify(ChangeEvent event) { Set<URI> affectedElements = registration.getAffectedModelElements((ModelChangeEvent) event, connection); ok[0] = affectedElements.size() == 1 && affectedElements.iterator().next().getMofId().equals(cl1.refMofId()); } }; connection.getEventRegistry().registerListener(listener, eventFilter); try { cl1.setName("ChangedHumba1"); assertTrue(ok[0]); } finally { connection.getEventRegistry().deregister(listener); } } @Test public void testVerySimpleTracerBasedInstanceScopeAnalysis() throws OclManagerException { final OclExpressionRegistration registration = MetamodelUtils.createOclExpression(connection, "testVerySimpleTracerBasedInstanceScopeAnalysis", "self.oclAsType(data::classes::SapClass).name", SapClass.CLASS_DESCRIPTOR); final SapClass cl1 = connection.createElement(SapClass.CLASS_DESCRIPTOR); cl1.setName("HumbaClass1"); EventFilter eventFilter = registration.getEventFilter(false); final boolean[] ok = new boolean[1]; ChangeListener listener = new ChangeListener() { @Override public void notify(ChangeEvent event) { Set<URI> affectedElements = registration.getAffectedModelElements((ModelChangeEvent) event, connection); ok[0] = affectedElements.size() == 1 && affectedElements.iterator().next().getMofId().equals(cl1.refMofId()); } }; connection.getEventRegistry().registerListener(listener, eventFilter); try { cl1.setName("ChangedHumba1"); assertTrue(ok[0]); } finally { connection.getEventRegistry().deregister(listener); } } @Test public void testGetFloorTokenNull() throws OclManagerException { ObjectLiteral ol = connection.createElement(ObjectLiteral.CLASS_DESCRIPTOR); SapClass cl1 = connection.createElement(SapClass.CLASS_DESCRIPTOR); cl1.setName("HumbaClass1"); cl1.setValueType(true); ol.setValueClass(cl1); Association a = connection.createElement(Association.CLASS_DESCRIPTOR); a.setName("Assoc"); AssociationEnd ae1 = connection.createElement(AssociationEnd.CLASS_DESCRIPTOR); ae1.setName("Humba1"); ae1.setType(MetamodelUtils.createClassTypeDefinitionExactlyOne(connection, cl1)); a.getEnds().add(ae1); AssociationEnd ae2 = connection.createElement(AssociationEnd.CLASS_DESCRIPTOR); ae2.setName("Humba2"); SapClass cl2 = connection.createElement(SapClass.CLASS_DESCRIPTOR); cl2.setName("HumbaClass2"); ae2.setType(MetamodelUtils.createClassTypeDefinitionExactlyOne(connection, cl2)); a.getEnds().add(ae2); OclRegistryService oclRegistry = connection.getOclRegistryService(); final OclExpressionRegistration registration = oclRegistry.getFreestyleRegistry().createExpressionRegistration( "testForIA2", "self.oclAsType(dataaccess::expressions::literals::ObjectLiteral).valueClass.getAssociationEnds().otherEnd()" + "->select(ae|ae.name='Humba')", OclRegistrationSeverity.Info, new String[] { "TestOclIA" }, connection.getClass(ObjectLiteral.CLASS_DESCRIPTOR), new RefPackage[] { connection.getPackage(NgpmPackage.PACKAGE_DESCRIPTOR) }); EventFilter eventFilter = registration.getEventFilter(/* notifyNewContextElement */ true); ChangeListener listener = new ChangeListener() { @Override public void notify(ChangeEvent event) { Set<URI> affectedElements = registration.getAffectedModelElements((ModelChangeEvent) event, connection); Set<RefBaseObject> elements = new HashSet<RefBaseObject>(); for (URI affectedElementMri : affectedElements) { elements.add(connection.getElement(affectedElementMri)); } } }; connection.getEventRegistry().registerListener(listener, eventFilter); try { ae1.setName("ChangedHumba1"); } finally { connection.getEventRegistry().deregister(listener); } } }