diff --git a/dumpAst/src/main/jastadd/DumpAst.relast b/dumpAst/src/main/jastadd/DumpAst.relast index 730a4245e198b562ba06b1591c91dfe73285a3b3..c1b1ed92c553bcdf7950bec1f328e4e6fac9777b 100644 --- a/dumpAst/src/main/jastadd/DumpAst.relast +++ b/dumpAst/src/main/jastadd/DumpAst.relast @@ -1,5 +1,5 @@ DumpAst ::= DumpNode* <PackageName> BuildConfig PrintConfig ; -BuildConfig ::= <TypeIgnore> <TokenIgnore> <ChildIgnore> <AttributeIgnore> <RelationIgnore> <IncludeEmptyString:boolean> <Debug:boolean> ; +BuildConfig ::= <TypeIgnore> <TokenIgnore> <ChildIgnore> <AttributeInclude> <NonterminalAttributeInclude> <RelationIgnore> <IncludeEmptyString:boolean> <Debug:boolean> ; PrintConfig ::= <Scale:double> <Version> Header* ; Header ::= <Value> ; DumpNode ::= <Name> <Label> <Object:Object> <Invisible:boolean> DumpChildNode* DumpToken* DumpRelation* /InvisiblePath/ ; diff --git a/dumpAst/src/main/jastadd/Generation.jadd b/dumpAst/src/main/jastadd/Generation.jadd index ee53e202e266792124b1ad83392e281e1d5533ab..c1d02452dc9af86de8f928f831b8d272681806f1 100644 --- a/dumpAst/src/main/jastadd/Generation.jadd +++ b/dumpAst/src/main/jastadd/Generation.jadd @@ -60,7 +60,7 @@ import java.lang.String;aspect GenerationFrontend { * @see java.util.regex.Pattern#compile(java.lang.String) */ public DumpBuilder disableTypes(String... regexes) { - updateIgnored(() -> buildConfig.getTypeIgnore(), s -> buildConfig.setTypeIgnore(s), regexes); + updateRegexes(() -> buildConfig.getTypeIgnore(), s -> buildConfig.setTypeIgnore(s), regexes); return this; } @@ -71,44 +71,45 @@ import java.lang.String;aspect GenerationFrontend { * @see java.util.regex.Pattern#compile(java.lang.String) */ public DumpBuilder excludeTokens(String... regexes) { - updateIgnored(() -> buildConfig.getTokenIgnore(), s -> buildConfig.setTokenIgnore(s), regexes); + updateRegexes(() -> buildConfig.getTokenIgnore(), s -> buildConfig.setTokenIgnore(s), regexes); return this; } // not supported yet public DumpBuilder includeAttributes(String... regexes) { - updateIgnored(() -> buildConfig.getAttributeIgnore(), s -> buildConfig.setAttributeIgnore(s), regexes); + updateRegexes(() -> buildConfig.getAttributeInclude(), s -> buildConfig.setAttributeInclude(s), regexes); return this; } // not supported yet public DumpBuilder includeNonterminalAttributes(String... regexes) { - // TODO + updateRegexes(() -> buildConfig.getNonterminalAttributeInclude(), s -> buildConfig.setNonterminalAttributeInclude(s), regexes); return this; } /** * Exclude every child whose name (i.e., context) matches at least on of the given regex strings. - * Unlike disabling types, the complete object and its (transitive) children won't be included in any output. + * This means, that the complete object and its (transitive) children will never be included in any output. * @param regexes regex patterns to match child names * @return this * @see java.util.regex.Pattern#compile(java.lang.String) */ public DumpBuilder excludeChildren(String... regexes) { - updateIgnored(() -> buildConfig.getChildIgnore(), s -> buildConfig.setChildIgnore(s), regexes); + updateRegexes(() -> buildConfig.getChildIgnore(), s -> buildConfig.setChildIgnore(s), regexes); return this; } /** * Exclude every relation whose role-name matches at least on of the given regex strings. - * Unlike disabling types, the complete object and its (transitive) children won't be included in any output, except. + * This means two things: a) the relation to any potential target object(s) is never shown, and b) the target + * object(s) are not shown unless they are reachable by another relation or by containment. * @param regexes regex patterns to match child names * @return this * @see java.util.regex.Pattern#compile(java.lang.String) */ public DumpBuilder excludeRelations(String... regexes) { - updateIgnored(() -> buildConfig.getRelationIgnore(), s -> buildConfig.setRelationIgnore(s), regexes); + updateRegexes(() -> buildConfig.getRelationIgnore(), s -> buildConfig.setRelationIgnore(s), regexes); return this; } - private void updateIgnored(java.util.function.Supplier<String> getter, java.util.function.Consumer<String> setter, String... values) { + private void updateRegexes(java.util.function.Supplier<String> getter, java.util.function.Consumer<String> setter, String... values) { for (String value : values) { if (getter.get().isEmpty()) { setter.accept(value); @@ -209,28 +210,59 @@ import java.lang.String;aspect GenerationFrontend { } aspect GenerationBackend { + class DumpAst { + private enum Source { + RELATION, INVISIBLE_PARENT, PARENT, ROOT + } + } + // --- transform --- (need to be a method, because it alters the AST while traversing the object structure) - // maybe return type is unncessary protected DumpNode DumpAst.transform(TransformationTransferInformation tti, Object obj) throws java.lang.reflect.InvocationTargetException, IllegalAccessException, NoSuchMethodException { + DumpNode result = transform(tti, obj, Source.ROOT); + // post-process relationTargetsUnprocessed + boolean someAreUnprocessed = true; + while (someAreUnprocessed) { + someAreUnprocessed = false; + java.util.Map<DumpNode, Boolean> copy = new java.util.HashMap<>(tti.relationTargetsUnprocessed); + for (java.util.Map.Entry<DumpNode, Boolean> entry : copy.entrySet()) { + if (entry.getValue()) { + transform(tti, entry.getKey().getObject(), Source.ROOT); + someAreUnprocessed = true; + } + } + } + return result; + } + protected DumpNode DumpAst.transform(TransformationTransferInformation tti, Object obj, Source source) + throws java.lang.reflect.InvocationTargetException, IllegalAccessException, NoSuchMethodException { if (obj == null) { return null; } - if (tti.transformed.containsKey(obj)) { - return tti.transformed.get(obj); - } -// tti.transformed.put(obj, null); -// return null; - DumpNode node = new DumpNode(); - node.setObject(obj); - node.setLabel(obj.getClass().getSimpleName() + "@" + obj.hashCode()); - node.setName("node" + tti.transformed.size()); - tti.transformed.put(obj, node); - this.addDumpNode(node); - if (matches(getBuildConfig().typeIgnorePattern(), obj.getClass().getSimpleName())) { - node.setInvisible(true); + DumpNode node = tti.transformed.get(obj); + if (node != null) { + if (source == Source.RELATION) { + return node; + } + // either processing as parent, or later as root-node. so mark it as processed. + tti.relationTargetsUnprocessed.put(node, false); + } else { + node = new DumpNode(); + node.setObject(obj); + node.setLabel(obj.getClass().getSimpleName() + "@" + obj.hashCode()); + node.setName("node" + tti.transformed.size()); + tti.transformed.put(obj, node); + this.addDumpNode(node); } if (node.isAstNode()) { + // do not process node further if coming from a relation + if (source == Source.RELATION) { + tti.relationTargetsUnprocessed.put(node, true); + return node; + } + if (source == Source.INVISIBLE_PARENT || matches(getBuildConfig().typeIgnorePattern(), obj.getClass().getSimpleName())) { + node.setInvisible(true); + } // only caching node.analyseClass does not help, since we want to do this only once per class of a node final ClassAnalysisResult car; Class<?> clazz = obj.getClass(); @@ -243,10 +275,11 @@ aspect GenerationBackend { // -- singleChild -- for (java.lang.reflect.Method method : car.singleChildMethods) { Object target = method.invoke(obj); - DumpNode targetNode = transform(tti, target); + String childName = car.names.get(method); + DumpNode targetNode = transform(tti, target, nextSource(source, matches(getBuildConfig().childIgnorePattern(), childName))); if (target != null && targetNode != null) { DumpNormalChildNode normalChild = new DumpNormalChildNode(); - normalChild.setName(car.names.get(method)); + normalChild.setName(childName); normalChild.setDumpNode(targetNode); node.addDumpChildNode(normalChild); } @@ -255,9 +288,11 @@ aspect GenerationBackend { for (java.lang.reflect.Method method : car.listChildMethods) { Iterable<?> targetList = (Iterable<?>) method.invoke(obj); DumpListChildNode listChild = new DumpListChildNode(); - listChild.setName(car.names.get(method)); + String childName = car.names.get(method); + boolean shouldBeInvisisble = matches(getBuildConfig().childIgnorePattern(), childName); + listChild.setName(childName); for (Object target : targetList) { - DumpNode targetNode = transform(tti, target); + DumpNode targetNode = transform(tti, target, nextSource(source, shouldBeInvisisble)); if (target != null && targetNode != null) { listChild.addInnerDumpNode(new InnerDumpNode(targetNode)); } @@ -269,7 +304,7 @@ aspect GenerationBackend { // -- singleRelation -- for (java.lang.reflect.Method method : car.singleRelationMethods) { Object target = method.invoke(obj); - DumpNode targetNode = transform(tti, target); + DumpNode targetNode = transform(tti, target, Source.RELATION); if (target != null && targetNode != null) { DumpNormalRelation normalRelation = new DumpNormalRelation(); normalRelation.setName(car.names.get(method)); @@ -283,7 +318,7 @@ aspect GenerationBackend { DumpListRelation listRelation = new DumpListRelation(); listRelation.setName(car.names.get(method)); for (Object target : targetList) { - DumpNode targetNode = transform(tti, target); + DumpNode targetNode = transform(tti, target, Source.RELATION); if (target != null && targetNode != null) { listRelation.addInnerDumpNode(new InnerDumpNode(targetNode)); } @@ -296,8 +331,10 @@ aspect GenerationBackend { for (java.lang.reflect.Method method : car.tokenMethods) { Object target = method.invoke(obj); if (target != null) { - DumpNode targetNode = transform(tti, target); + DumpNode targetNode = transform(tti, target, Source.RELATION); DumpToken token = null; + // TODO check, if Iterable.isAssignableFrom(target.getClass()). + // if so, check isAstNode for first non-null to add DumpReferenceToken's, otherwise DumpValueToken's if (targetNode != null && targetNode.isAstNode()) { token = new DumpReferenceToken().setValue(targetNode); } else { @@ -317,6 +354,11 @@ aspect GenerationBackend { return node; } + private Source DumpAst.nextSource(Source currentSource, boolean shouldBeInvisible) { + return currentSource == Source.INVISIBLE_PARENT ? Source.INVISIBLE_PARENT : + (shouldBeInvisible ? Source.INVISIBLE_PARENT : Source.PARENT); + } + ClassAnalysisResult DumpNode.analyzeClass() throws java.lang.reflect.InvocationTargetException, IllegalAccessException, NoSuchMethodException { ClassAnalysisResult result = new ClassAnalysisResult(); @@ -329,31 +371,25 @@ aspect GenerationBackend { switch (simpleName) { case "Child": String singleChildName = invokeName(annotation); - if (!matches(buildConfig().childIgnorePattern(), singleChildName)) { - result.singleChildMethods.add(method); - result.names.put(method, singleChildName); - } + result.singleChildMethods.add(method); + result.names.put(method, singleChildName); break; case "OptChild": String optChildName = invokeName(annotation); - if (!matches(buildConfig().childIgnorePattern(), optChildName)) { - try { - // the annotated method is "get???Opt", but we want "get???" - java.lang.reflect.Method realGetter = clazz.getMethod("get" + optChildName); - result.singleChildMethods.add(realGetter); - result.names.put(realGetter, optChildName); - } catch (NoSuchMethodException e) { - System.err.println("Could not find getter for Opt-child " + optChildName + " in " + clazz.getName()); - throw new RuntimeException(e); - } + try { + // the annotated method is "get???Opt", but we want "get???" + java.lang.reflect.Method realGetter = clazz.getMethod("get" + optChildName); + result.singleChildMethods.add(realGetter); + result.names.put(realGetter, optChildName); + } catch (NoSuchMethodException e) { + System.err.println("Could not find getter for Opt-child " + optChildName + " in " + clazz.getName()); + throw new RuntimeException(e); } break; case "ListChild": String listChildName = invokeName(annotation); - if (!matches(buildConfig().childIgnorePattern(), listChildName)) { - result.listChildMethods.add(method); - result.names.put(method, listChildName); - } + result.listChildMethods.add(method); + result.names.put(method, listChildName); break; case "Token": // heuristic for relations @@ -390,8 +426,23 @@ aspect GenerationBackend { } break; case "Attribute": - // TODO. check for isNTA=true. then check for whether target is instance of iterable. if so, add to listChildren, otherwise to singelChild - // TODO. if isNTA=false, then handle attribute + String attributeName = method.getName(); + boolean isNTA = (boolean) annotation.annotationType().getMethod("isNTA").invoke(annotation); + if (isNTA) { + if (matches(buildConfig().ntaIncludePattern(), attributeName)) { + if (Iterable.class.isAssignableFrom(method.getReturnType())) { + result.listChildMethods.add(method); + result.names.put(method, attributeName + "()"); + } else { + result.singleChildMethods.add(method); + result.names.put(method, attributeName + "()"); + } + } + } else if (matches(buildConfig().attributeIncludePattern(), attributeName)) { + // normal attribute + result.tokenMethods.add(method); + result.names.put(method, attributeName + "()"); + } break; } } @@ -410,7 +461,8 @@ aspect GenerationBackend { syn java.util.regex.Pattern BuildConfig.typeIgnorePattern() = java.util.regex.Pattern.compile(getTypeIgnore()); syn java.util.regex.Pattern BuildConfig.childIgnorePattern() = java.util.regex.Pattern.compile(getChildIgnore()); syn java.util.regex.Pattern BuildConfig.tokenIgnorePattern() = java.util.regex.Pattern.compile(getTokenIgnore()); - syn java.util.regex.Pattern BuildConfig.attributeIgnorePattern() = java.util.regex.Pattern.compile(getAttributeIgnore()); + syn java.util.regex.Pattern BuildConfig.attributeIncludePattern() = java.util.regex.Pattern.compile(getAttributeInclude()); + syn java.util.regex.Pattern BuildConfig.ntaIncludePattern() = java.util.regex.Pattern.compile(getNonterminalAttributeInclude()); syn java.util.regex.Pattern BuildConfig.relationIgnorePattern() = java.util.regex.Pattern.compile(getRelationIgnore()); static boolean ASTNode.matches(java.util.regex.Pattern p, String input) { return p.matcher(input).matches(); @@ -468,6 +520,7 @@ aspect GenerationBackend { class TransformationTransferInformation { java.util.Map<Object, DumpNode> transformed = new java.util.HashMap<>(); + java.util.Map<DumpNode, Boolean> relationTargetsUnprocessed = new java.util.HashMap<>(); java.util.Map<Class<?>, ClassAnalysisResult> classAnalysisResults = new java.util.HashMap<>(); } diff --git a/dumpAst/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/SimpleMain.java b/dumpAst/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/SimpleMain.java index 454a6ae77f3bd5594b979ef250ab2c1148d3d085..2ff16f10f735c1903c36d8d89b05eeb710a8b732 100644 --- a/dumpAst/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/SimpleMain.java +++ b/dumpAst/src/main/java/de/tudresden/inf/st/jastadd/dumpAst/SimpleMain.java @@ -2,6 +2,8 @@ package de.tudresden.inf.st.jastadd.dumpAst; import beaver.Parser; import de.tudresden.inf.st.jastadd.dumpAst.ast.*; +import de.tudresden.inf.st.jastadd.dumpAst.ast.ASTNode; +import de.tudresden.inf.st.jastadd.dumpAst.ast.JastAddList; import de.tudresden.inf.st.jastadd.grammar2uml.ast.*; import de.tudresden.inf.st.jastadd.grammar2uml.parser.Grammar2UmlParser; import de.tudresden.inf.st.jastadd.grammar2uml.scanner.Grammar2UmlScanner; @@ -16,6 +18,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashSet; +import java.util.List; import java.util.Set; import static de.tudresden.inf.st.jastadd.dumpAst.SimpleMain.Kind.*; @@ -119,6 +122,7 @@ public class SimpleMain { .disableTypes(".*Comment") .dumpAsSource(Paths.get("temp.plantuml")) .dumpAsSVG(Paths.get("temp.svg")); + System.out.println(Iterable.class.getMethods()[0].getReturnType()); } private static void small() throws IOException { diff --git a/dumpAst/src/main/resources/dumpAst.mustache b/dumpAst/src/main/resources/dumpAst.mustache index b8105eef93ba3054c4ff207abf38c233af8e0cb7..b0c05305e6ff1c6431d593d7628101c90b3230bc 100644 --- a/dumpAst/src/main/resources/dumpAst.mustache +++ b/dumpAst/src/main/resources/dumpAst.mustache @@ -1,76 +1,76 @@ @startuml {{#PrintConfig}} scale {{Scale}} -{{#Headers}} + {{#Headers}} {{Value}} -{{/Headers}} + {{/Headers}} {{/PrintConfig}} {{#DumpNodes}} -{{#isAstNode}} -{{^Invisible}} + {{#isAstNode}} + {{^Invisible}} object "{{label}}" as {{name}} { -{{#DumpTokens}} -{{#isDumpValueToken}} + {{#DumpTokens}} + {{#isDumpValueToken}} {{label}} = {{{Value}}} -{{/isDumpValueToken}} -{{/DumpTokens}} + {{/isDumpValueToken}} + {{/DumpTokens}} } -{{/Invisible}} -{{/isAstNode}} + {{/Invisible}} + {{/isAstNode}} {{/DumpNodes}} {{#DumpNodes}} -{{#DumpTokens}} -{{^Invisible}} -{{^isDumpValueToken}} + {{#DumpTokens}} + {{^Invisible}} + {{^isDumpValueToken}} {{outerNodeName}} ..> {{innerNodeName}} : {{label}} -{{/isDumpValueToken}} -{{/Invisible}} -{{/DumpTokens}} -{{#DumpChildNodes}} -{{#isList}} -{{#InnerDumpNodes}} -{{#bothVisible}} + {{/isDumpValueToken}} + {{/Invisible}} + {{/DumpTokens}} + {{#DumpChildNodes}} + {{#isList}} + {{#InnerDumpNodes}} + {{#bothVisible}} {{outerNodeName}} *-- {{innerNodeName}} : {{label}} -{{/bothVisible}} -{{/InnerDumpNodes}} -{{/isList}} -{{^isList}} -{{#bothVisible}} + {{/bothVisible}} + {{/InnerDumpNodes}} + {{/isList}} + {{^isList}} + {{#bothVisible}} {{outerNodeName}} *-- {{innerNodeName}} : {{label}} -{{/bothVisible}} -{{/isList}} -{{/DumpChildNodes}} -{{#DumpRelations}} -{{#isList}} -{{#InnerDumpNodes}} -{{#bothVisible}} + {{/bothVisible}} + {{/isList}} + {{/DumpChildNodes}} + {{#DumpRelations}} + {{#isList}} + {{#InnerDumpNodes}} + {{#bothVisible}} {{outerNodeName}} {{#Bidirectional}}<{{/Bidirectional}}--> {{innerNodeName}} : {{label}} -{{/bothVisible}} -{{/InnerDumpNodes}} -{{/isList}} -{{^isList}} -{{#bothVisible}} + {{/bothVisible}} + {{/InnerDumpNodes}} + {{/isList}} + {{^isList}} + {{#bothVisible}} {{outerNodeName}} {{#Bidirectional}}<{{/Bidirectional}}--> {{innerNodeName}} : {{label}} -{{/bothVisible}} -{{/isList}} -{{/DumpRelations}} -{{^Invisible}} -{{#InvisiblePath}} -{{#InnerDumpNodes}} + {{/bothVisible}} + {{/isList}} + {{/DumpRelations}} + {{^Invisible}} + {{#InvisiblePath}} + {{#InnerDumpNodes}} {{outerNodeName}} o.. {{innerNodeName}} -{{/InnerDumpNodes}} -{{/InvisiblePath}} -{{/Invisible}} + {{/InnerDumpNodes}} + {{/InvisiblePath}} + {{/Invisible}} {{/DumpNodes}} {{#BuildConfig}} -{{#Debug}} + {{#Debug}} legend right %date() dumpAst: {{version}} plantuml: %version() endlegend -{{/Debug}} + {{/Debug}} {{/BuildConfig}} @enduml diff --git a/testDumper/src/main/jastadd/testDumper.jrag b/testDumper/src/main/jastadd/testDumper.jrag index c27464bea4ff4586b04c35efdb77a20412b3e36e..7c98b5787378aecfed4eae0e08664f704cb68c58 100644 --- a/testDumper/src/main/jastadd/testDumper.jrag +++ b/testDumper/src/main/jastadd/testDumper.jrag @@ -26,4 +26,7 @@ aspect Grammar { result.add(inner); return result; } + + syn int Root.simpleAttr() = 42; + syn A Root.referenceAttr() = getA(); } diff --git a/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestExcluded.java b/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestExcluded.java index 4faf6639b16f68cd1fae55527a9a4a97425cec5f..87588648dad540b88ba856b349c57c4a95d84cd3 100644 --- a/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestExcluded.java +++ b/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestExcluded.java @@ -270,7 +270,7 @@ public class TestExcluded { } @Test - public void testChildrenDefault() throws IOException { + public void testChildrenDefault() { /* Root |- a |- b - - -. @@ -286,7 +286,6 @@ public class TestExcluded { }), null); root.getA().getB().setOneA(root.getA().getMyC().getA()); - Dumper.read(root).disableTypes("C").dumpAsPNG(Paths.get("test.png")); List<DumpNode> nodes = TestUtils.dumpModel(root); assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder( ROOT_NAME, A_NAME, A2_Name, B_NAME, B2_NAME, C_NAME); @@ -295,7 +294,6 @@ public class TestExcluded { tuple("MyC", C_NAME), tuple("B", B_NAME)); } - @Disabled("a2 and b2 are included in output, so currently not working as intended") @Test public void testChildrenExclude() { /* Root diff --git a/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestIncluded.java b/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestIncluded.java new file mode 100644 index 0000000000000000000000000000000000000000..7973addd20f1ba2afbd78626af9e2927b4c26546 --- /dev/null +++ b/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestIncluded.java @@ -0,0 +1,97 @@ +package de.tudresden.inf.st.jastadd.testDumper; + +import de.tudresden.inf.st.jastadd.dumpAst.ast.DumpNode; +import org.jastadd.testDumper.ast.Root; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static de.tudresden.inf.st.jastadd.testDumper.TestUtils.*; +import static org.assertj.core.api.Assertions.*; + +public class TestIncluded { + + @Test + public void testValueAttributeDefault() { + Root root = createRoot(null, null); + + List<DumpNode> nodes = TestUtils.dumpModel(root); + assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactly(ROOT_NAME); + DumpNode actualRoot = TestUtils.findByName(nodes, ROOT_NAME); + assertThat(valueTokens(actualRoot)).containsOnly(entry("Name", ROOT_NAME)); + } + + @Test + public void testValueAttributeIncluded() { + Root root = createRoot(null, null); + + List<DumpNode> nodes = TestUtils.dumpModel(root, db -> db.includeAttributes("simpleAttr")); + assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactly(ROOT_NAME); + DumpNode actualRoot = TestUtils.findByName(nodes, ROOT_NAME); + assertThat(valueTokens(actualRoot)).containsOnly(entry("Name", ROOT_NAME), entry("simpleAttr()", 42)); + } + + @Test + public void testReferenceAttributeDefault() { + Root root = createRoot(createA(A_NAME), null); + + List<DumpNode> nodes = TestUtils.dumpModel(root); + assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactly(ROOT_NAME, A_NAME); + DumpNode actualRoot = TestUtils.findByName(nodes, ROOT_NAME); + assertThat(referenceTokens(actualRoot)).isEmpty(); + } + + @Test + public void testReferenceAttributeIncluded() { + Root root = createRoot(createA(A_NAME), null); + + List<DumpNode> nodes = TestUtils.dumpModel(root, db -> db.includeAttributes("referenceAttr")); + assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactly(ROOT_NAME, A_NAME); + DumpNode actualRoot = TestUtils.findByName(nodes, ROOT_NAME); + assertThatMapOf(referenceTokens(actualRoot)).containsOnly(tuple("referenceAttr()", A_NAME)); + } + + @Test + public void testNormalNTADefault() { + Root root = createRoot(null, createC(C_NAME)); + + List<DumpNode> nodes = TestUtils.dumpModel(root); + assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactly(ROOT_NAME, C_NAME); + DumpNode actualC = TestUtils.findByName(nodes, C_NAME); + assertThatMapOf(normalChildren(actualC)).isEmpty(); + } + + @Test + public void testNormalNTAIncluded() { + Root root = createRoot(null, createC(C_NAME)); + + List<DumpNode> nodes = TestUtils.dumpModel(root, db -> db.includeNonterminalAttributes("getCalculated")); + assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactly(ROOT_NAME, C_NAME, "Calculated-" + C_NAME); + DumpNode actualC = TestUtils.findByName(nodes, C_NAME); + assertThatMapOf(normalChildren(actualC)).containsOnly(tuple("getCalculated()", "Calculated-" + C_NAME)); + } + + @Test + public void testListNTADefault() { + Root root = createRoot(null, createC(C_NAME)); + + List<DumpNode> nodes = TestUtils.dumpModel(root); + assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactly(ROOT_NAME, C_NAME); + DumpNode actualC = TestUtils.findByName(nodes, C_NAME); + assertThat(listChildren(actualC)).isEmpty(); + + } + + @Disabled("NTA lists not working at the moment") + @Test + public void testListNTAIncluded() { + // TODO make the test not failing + Root root = createRoot(null, createC(C_NAME)); + + List<DumpNode> nodes = TestUtils.dumpModel(root, db -> db.includeNonterminalAttributes("AlsoCalculated")); + assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactly(ROOT_NAME, C_NAME, "AlsoCalculated-" + C_NAME); + DumpNode actualC = TestUtils.findByName(nodes, C_NAME); + assertThatMapOf(listChildren(actualC), "getAlsoCalculated()").containsExactly("AlsoCalculated-" + C_NAME); + } +} diff --git a/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestSimple.java b/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestSimple.java index d40a297d95223a7e989ccdbcdeac08516f53d9a6..9f45108fb7b6eaceb51424605e457d1e3efd052f 100644 --- a/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestSimple.java +++ b/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestSimple.java @@ -30,7 +30,6 @@ public class TestSimple { Root root = createRoot(createA(A_NAME), null); List<DumpNode> nodes = TestUtils.dumpModel(root); - assertEquals(2, nodes.size()); assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(ROOT_NAME, A_NAME); DumpNode actualRoot = TestUtils.findByName(nodes, ROOT_NAME); assertEquals(1, actualRoot.getNumDumpToken()); @@ -57,7 +56,6 @@ public class TestSimple { Root root = createRoot(null, createC(C_NAME)); List<DumpNode> nodes = TestUtils.dumpModel(root); - assertEquals(2, nodes.size()); assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(ROOT_NAME, C_NAME); DumpNode actualRoot = TestUtils.findByName(nodes, ROOT_NAME); assertEquals(1, actualRoot.getNumDumpToken()); @@ -72,7 +70,7 @@ public class TestSimple { root.getB(0).setOneA(root.getA()); List<DumpNode> nodes = TestUtils.dumpModel(root); - assertEquals(4, nodes.size()); + assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(ROOT_NAME, A_NAME, B_NAME, C_NAME); DumpNode actualB = TestUtils.findByName(nodes, B_NAME); assertThatMapOf(normalRelationChildren(actualB)).containsExactlyInAnyOrder(tuple("OneA", A_NAME)); } @@ -97,7 +95,7 @@ public class TestSimple { root.getB(0).setMaybeC(root.getC()); List<DumpNode> nodes = TestUtils.dumpModel(root); - assertEquals(4, nodes.size()); + assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(ROOT_NAME, A_NAME, B_NAME, C_NAME); DumpNode actualB = TestUtils.findByName(nodes, B_NAME); assertThatMapOf(normalRelationChildren(actualB)).containsExactlyInAnyOrder(tuple("MaybeC", C_NAME)); } @@ -108,7 +106,7 @@ public class TestSimple { root.getC().setBiA1(root.getA()); List<DumpNode> nodes = TestUtils.dumpModel(root); - assertEquals(4, nodes.size()); + assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(ROOT_NAME, A_NAME, B_NAME, C_NAME); // bidirectional relations are currently not found, instead there will be two unidirectional ones DumpNode actualA = TestUtils.findByName(nodes, A_NAME); assertThatMapOf(normalRelationChildren(actualA)).containsExactlyInAnyOrder(tuple("BiC1", C_NAME)); @@ -122,7 +120,7 @@ public class TestSimple { root.getC().addBiA2(root.getA()); List<DumpNode> nodes = TestUtils.dumpModel(root); - assertEquals(4, nodes.size()); + assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(ROOT_NAME, A_NAME, B_NAME, C_NAME); // bidirectional relations are currently not found, instead there will be two unidirectional ones DumpNode actualA = TestUtils.findByName(nodes, A_NAME); assertThatMapOf(normalRelationChildren(actualA)).containsExactlyInAnyOrder(tuple("BiC2", C_NAME)); @@ -136,7 +134,7 @@ public class TestSimple { root.getC().setBiA3(root.getA()); List<DumpNode> nodes = TestUtils.dumpModel(root); - assertEquals(4, nodes.size()); + assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(ROOT_NAME, A_NAME, B_NAME, C_NAME); // bidirectional relations are currently not found, instead there will be two unidirectional ones DumpNode actualA = TestUtils.findByName(nodes, A_NAME); assertThatMapOf(normalRelationChildren(actualA)).containsExactlyInAnyOrder(tuple("BiC3", C_NAME)); @@ -150,7 +148,7 @@ public class TestSimple { root.getC().setRawReference(root.getA()); List<DumpNode> nodes = TestUtils.dumpModel(root); - assertEquals(4, nodes.size()); + assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(ROOT_NAME, A_NAME, B_NAME, C_NAME); DumpNode actualC = TestUtils.findByName(nodes, C_NAME); assertThatMapOf(referenceTokens(actualC)).containsExactlyInAnyOrder(tuple(TOKEN_LABEL_RAW_REFERENCE, A_NAME)); }