package com.sap.furcas.referenceresolving.tests; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import java.io.File; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.ocl.ecore.opposites.DefaultOppositeEndFinder; import org.eclipse.ocl.ecore.opposites.OppositeEndFinder; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import com.sap.furcas.metamodel.FURCAS.textblocks.TextBlock; import com.sap.furcas.metamodel.FURCAS.textblocks.TextblocksPackage; import com.sap.furcas.test.fixture.ScenarioFixtureData; import com.sap.ide.cts.parser.errorhandling.SemanticParserException; /** * A test case that use a FURCAS mapping specification (".tcs" file) and based on this produce lexer and * parser, then parse a text resource and register all reference resolving callbacks. Then, the test * manipulates the model produced by the parser run and observes how OCL-based property assignments get re-assigned. * * @author Axel Uhl (D043530) * */ public class TestPropertyInitReEvaluationWithTextBlocks extends AbstractReferenceResolvingTest { private static final String LANGUAGE = "BibtexWithPropertyInits"; private static final File TCS = new File("fixtures/BibtexWithPropertyInits.tcs"); private static final File[] METAMODELS = { ScenarioFixtureData.BIBTEXT_METAMODEL, ScenarioFixtureData.BIBTEXT1_METAMODEL }; private EObject johnDoe; private EObject article; private EClass authorClass; private EClass articleClass; @BeforeClass public static void setupParser() throws Exception { setupParser(LANGUAGE, TCS, METAMODELS); } /** * Tests whether an simple addition to a textblock is correctly mapped to an insertion in the model without * re-creating the parent element. * * @throws Exception */ @Before public void setupInitialModel() throws SemanticParserException { String textToParse = "article{" + " Testing, \"John Doe\"," + " year = \"2002\"" + "}" + "author = \"John Doe\"." + "author = \"Jane Doll\"."; setupModelFromTextToParse(textToParse); johnDoe = null; article = null; authorClass = null; articleClass = null; assertNotNull(rootElement); EClass bibTexFileClass = rootElement.eClass(); assertEquals("BibTextFile", bibTexFileClass.getName()); @SuppressWarnings("unchecked") Collection<EObject> entries = (Collection<EObject>) rootElement.eGet(bibTexFileClass .getEStructuralFeature("entries")); for (EObject entry : entries) { if (entry.eClass().getName().equals("Author")) { authorClass = entry.eClass(); if (entry.eGet(authorClass.getEStructuralFeature("name")).equals("John Doe")) { johnDoe = entry; } } else if (entry.eClass().getName().equals("Article")) { articleClass = entry.eClass(); article = entry; } } } @Test public void testInitialModel() { assertNotNull(rootElement); EList<?> entries = (EList<?>) (rootElement).eGet((rootElement).eClass().getEStructuralFeature("entries")); assertEquals(3, entries.size()); assertNotNull(johnDoe); // now check the reference was set using the right property name // assertNotNull(johnDoe.get("articles")); StubModelHandler not powerful enough assertNotNull(article.eGet(articleClass.getEStructuralFeature("author"))); assertEquals(johnDoe, article.eGet(articleClass.getEStructuralFeature("author"))); assertEquals("Where John Doe wrote it", article.eGet(articleClass.getEStructuralFeature("location"))); } @Test public void testForeachPropertyInitValueInInitialModel() throws Exception { @SuppressWarnings("unchecked") EList<EObject> revenues = (EList<EObject>) johnDoe.eGet(authorClass.getEStructuralFeature("revenues")); @SuppressWarnings("unchecked") EList<EObject> johnsArticles = (EList<EObject>) johnDoe.eGet(authorClass.getEStructuralFeature("articles")); assertEquals(johnsArticles.size(), revenues.size()); Iterator<EObject> johnsArticlesIterator = johnsArticles.iterator(); for (EObject revenue : revenues) { EObject theArticle = johnsArticlesIterator.next(); assertSame(theArticle, revenue.eGet(revenue.eClass().getEStructuralFeature("article"))); assertEquals(((String) ((EObject) theArticle.eGet(articleClass.getEStructuralFeature("author"))).eGet( authorClass.getEStructuralFeature("name"))).length(), revenue.eGet( revenue.eClass().getEStructuralFeature("revenueInEUR"))); } } @Test public void testChangeOfExpressionValueUsingHashForeach() throws Exception { johnDoe.eSet(authorClass.getEStructuralFeature("name"), "The Only John Doe"); testForeachPropertyInitValueInInitialModel(); } @Test public void testChangeAuthorName() { johnDoe.eSet(authorClass.getEStructuralFeature("name"), "John Dough"); assertEquals("Where John Dough wrote it", article.eGet(articleClass.getEStructuralFeature("location"))); } /** * Tests that updating an author's name does not trigger the property init through the * impact analysis in case the author hasn't been created using concrete syntax and * therefore no text block exists for the property init's execution. */ @Test public void testChangeAuthorNameForAuthorNotCreatedByConcreteSyntax() { EObject newAuthor = authorClass.getEPackage().getEFactoryInstance().create(authorClass); johnDoe.eResource().getContents().add(newAuthor); EObject newAuthorsArticle = articleClass.getEPackage().getEFactoryInstance().create(articleClass); @SuppressWarnings("unchecked") EList<EObject> articleList = (EList<EObject>) newAuthor.eGet(authorClass.getEStructuralFeature("articles")); articleList.add(newAuthorsArticle); newAuthor.eSet(authorClass.getEStructuralFeature("name"), "The New Author"); assertNull(newAuthorsArticle.eGet(articleClass.getEStructuralFeature("location"))); } @Test public void testAddArticleAndExpectRevenueLedgerCreation() throws Exception { EObject newArticle = articleClass.getEPackage().getEFactoryInstance().create(articleClass); newArticle.eSet(articleClass.getEStructuralFeature("location"), "Location of the New Article"); @SuppressWarnings("unchecked") EList<EObject> johnsArticles = (EList<EObject>) johnDoe.eGet(authorClass.getEStructuralFeature("articles")); johnsArticles.add(newArticle); @SuppressWarnings("unchecked") EList<EObject> revenues = (EList<EObject>) johnDoe.eGet(authorClass.getEStructuralFeature("revenues")); assertEquals(johnsArticles.size(), revenues.size()); // now ensure that a ForEachContext has been created for the RevenueLedger construction OppositeEndFinder oppositeEndFinder = DefaultOppositeEndFinder.getInstance(); Set<EObject> johnsArticlesAsSet = new HashSet<EObject>(johnsArticles); Set<EObject> revenueLedgerArticles = new HashSet<EObject>(); for (EObject revenueLedger : revenues) { revenueLedgerArticles.add((EObject) revenueLedger.eGet(revenueLedger.eClass().getEStructuralFeature("article"))); assertEquals( ((String) ((EObject) ((EObject) revenueLedger.eGet(revenueLedger.eClass().getEStructuralFeature( "article"))).eGet(articleClass.getEStructuralFeature("author"))).eGet( authorClass.getEStructuralFeature("name"))).length(), revenueLedger.eGet( revenueLedger.eClass().getEStructuralFeature("revenueInEUR"))); assertEquals("Expected to find exactly one ForEachContext for produced RevenueLedger element "+revenueLedger, 1, oppositeEndFinder.navigateOppositePropertyWithBackwardScope( TextblocksPackage.eINSTANCE.getForEachExecution_ResultModelElement(), revenueLedger).size()); EObject author = revenueLedger.eContainer(); TextBlock authorCreationRecord = (TextBlock) oppositeEndFinder.navigateOppositePropertyWithBackwardScope( TextblocksPackage.eINSTANCE.getTextBlock_CorrespondingModelElements(), author).iterator().next(); assertEquals("Expected exactly as many ForEachContext records as we have RevenueLedger objects for author "+ author, revenues.size(), authorCreationRecord.getForEachExecutions().size()); } assertEquals(johnsArticlesAsSet, revenueLedgerArticles); } }