Skip to content
Snippets Groups Projects
Commit 644a5267 authored by René Schöne's avatar René Schöne
Browse files

WIP: type-level inclusion/exclusion.

- fixed bug in Compiler for "--version"
parent e8cc7649
No related branches found
No related tags found
No related merge requests found
DumpAst ::= DumpNode* <PackageName> BuildConfig PrintConfig ; DumpAst ::= DumpNode* <PackageName> BuildConfig PrintConfig ;
rel DumpAst.RootNode -> DumpNode ; rel DumpAst.RootNode -> DumpNode ;
BuildConfig ::= <TypeIgnore> <TokenIgnore> <ChildIgnore> <AttributeInclude> <NonterminalAttributeInclude> <RelationIgnore> <IncludeEmptyString:boolean> <Debug:boolean> ; BuildConfig ::= GlobalPatternCollection:PatternCollection ExcludeTypePattern:TypePatternCollectionMapping* IncludeTypePattern:TypePatternCollectionMapping* <TypeIgnorePattern> <IncludeEmptyString:boolean> <Debug:boolean> ;
TypePatternCollectionMapping ::= <TypeRegex> PatternCollection ;
PatternCollection ::= <TokenPattern> <ChildPattern> <RelationPattern> <AttributePattern> <NonterminalAttributePattern> ;
PrintConfig ::= <Scale:double> <Version> Header* ; PrintConfig ::= <Scale:double> <Version> Header* ;
Header ::= <Value> ; Header ::= <Value> ;
DumpNode ::= <Name> <Label> <Object:Object> <Invisible:boolean> DumpChildNode* DumpToken* DumpRelation* /InvisiblePath/ ; DumpNode ::= <Name> <Label> <Object:Object> <Invisible:boolean> DumpChildNode* DumpToken* DumpRelation* /InvisiblePath/ ;
......
import java.lang.String;aspect GenerationFrontend {
public class Dumper {
/**
* Prepare to read in the given object. Use the <code>dump*</code> methods to actually dump its content.
* @param obj the object to dump
* @return a builder to adjust dump options
*/
public static DumpBuilder read(Object obj) {
return new DumpBuilder(obj);
}
}
public enum SkinParamBooleanSetting {
/** Print in grayscale? */
Monochrome,
/** Use shadows? */
Shadowing,
/** Use handwritten style? */
Handwritten
}
public enum SkinParamStringSetting {
/** Set color of background */
backgroundColor
}
public class DumpBuilder {
private Object target;
private String packageName;
private DumpAst result;
private BuildConfig buildConfig = new BuildConfig();
private PrintConfig printConfig = new PrintConfig();
protected DumpBuilder(Object target) {
this.target = target;
printConfig.setScale(1);
printConfig.setVersion(readVersion());
}
/**
* Add debug information in dumped content, mainly version numbers.
* @return this
*/
public DumpBuilder enableDebug() {
buildConfig.setDebug(true);
return this;
}
/**
* Include empty strings for all tokens
* @return this
*/
public DumpBuilder includeEmptyStringsOnTokens() {
buildConfig.setIncludeEmptyString(true);
return this;
}
/**
* Disable all objects with types matching at least one of the given regex strings.
* Disabled objects won't be included in any output. However, their children are still processed.
* @param regexes patterns to match type names
* @return this
* @see java.util.regex.Pattern#compile(java.lang.String)
*/
public DumpBuilder disableTypes(String... regexes) {
updateRegexes(() -> buildConfig.getTypeIgnore(), s -> buildConfig.setTypeIgnore(s), regexes);
return this;
}
/**
* Exclude tokens and their value if the token name matches at least one of the given regex strings.
* @param regexes regex patterns to match token names
* @return this
* @see java.util.regex.Pattern#compile(java.lang.String)
*/
public DumpBuilder excludeTokens(String... regexes) {
updateRegexes(() -> buildConfig.getTokenIgnore(), s -> buildConfig.setTokenIgnore(s), regexes);
return this;
}
/**
* Include attributes (as tokens) and their value if the attribute name matches at least on of the given regex strings.
* @param regexes regex patterns to match token names
* @return this
* @see java.util.regex.Pattern#compile(java.lang.String)
*/
public DumpBuilder includeAttributes(String... regexes) {
updateRegexes(() -> buildConfig.getAttributeInclude(), s -> buildConfig.setAttributeInclude(s), regexes);
return this;
}
/**
* Includes nonterminal-attributes (as children) and their values if
* their attribute name matches at least on of the given regex strings.
* <br>
* <b>Note</b>: A leading "get" and a trailing "List" in the name will be removed prior to matching.
* Thus, it should not be contained in the regex either.
* @param regexes regex patterns to match token names
* @return this
* @see java.util.regex.Pattern#compile(java.lang.String)
*/
public DumpBuilder includeNonterminalAttributes(String... regexes) {
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.
* 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) {
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.
* 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) {
updateRegexes(() -> buildConfig.getRelationIgnore(), s -> buildConfig.setRelationIgnore(s), regexes);
return this;
}
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);
} else {
setter.accept(getter.get() + "|" + value);
}
}
}
public DumpBuilder customPreamble(String option) {
printConfig.addHeader(new Header(option));
return this;
}
public DumpBuilder skinParam(SkinParamStringSetting setting, String value) {
customPreamble("skinparam " + setting.toString() + " " + value);
return this;
}
public DumpBuilder skinParam(SkinParamBooleanSetting setting, boolean value) {
customPreamble("skinparam " + setting.toString() + " " + value);
return this;
}
public DumpBuilder setScale(double value) {
printConfig.setScale(value);
return this;
}
private String readVersion() {
try {
java.util.ResourceBundle resources = java.util.ResourceBundle.getBundle("dumpAstVersion");
return resources.getString("version");
} catch (java.util.MissingResourceException e) {
return "version ?";
}
}
protected DumpAst build() {
if (result == null) {
result = new DumpAst();
result.setPackageName(this.packageName == null ? this.target.getClass().getPackage().getName() : this.packageName);
result.setBuildConfig(this.buildConfig);
result.setPrintConfig(this.printConfig);
try {
result.transform(new TransformationTransferInformation(), this.target);
} catch (java.lang.reflect.InvocationTargetException e) {
throw new RuntimeException("Could not transform :(", e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Could not transform :(", e);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Could not transform :(", e);
}
}
return result;
}
/**
* Write out content as plantuml source code.
* @param destination path of destination file
* @return this
* @throws java.io.IOException if an I/O error happend during opening or writing in that file
*/
public DumpBuilder dumpAsSource(java.nio.file.Path destination) throws java.io.IOException {
String content = build().toPlantUml();
try (java.io.Writer writer = java.nio.file.Files.newBufferedWriter(destination)) {
writer.write(content);
}
return this;
}
public DumpBuilder dumpAsYaml(java.nio.file.Path destination, boolean prependCreationComment) throws java.io.IOException {
String content = build().toYaml(prependCreationComment);
try (java.io.Writer writer = java.nio.file.Files.newBufferedWriter(destination)) {
writer.write(content);
}
return this;
}
}
}
aspect GenerationBackend { aspect GenerationBackend {
class DumpAst { class DumpAst {
private enum Source { private enum Source {
...@@ -238,6 +30,7 @@ aspect GenerationBackend { ...@@ -238,6 +30,7 @@ aspect GenerationBackend {
return null; return null;
} }
DumpNode node = tti.transformed.get(obj); DumpNode node = tti.transformed.get(obj);
String objClassName = obj.getClass().getSimpleName();
if (node != null) { if (node != null) {
if (source == Source.RELATION) { if (source == Source.RELATION) {
return node; return node;
...@@ -247,7 +40,7 @@ aspect GenerationBackend { ...@@ -247,7 +40,7 @@ aspect GenerationBackend {
} else { } else {
node = new DumpNode(); node = new DumpNode();
node.setObject(obj); node.setObject(obj);
node.setLabel(obj.getClass().getSimpleName() + "@" + obj.hashCode()); node.setLabel(objClassName + "@" + obj.hashCode());
node.setName("node" + tti.transformed.size()); node.setName("node" + tti.transformed.size());
tti.transformed.put(obj, node); tti.transformed.put(obj, node);
this.addDumpNode(node); this.addDumpNode(node);
...@@ -258,7 +51,7 @@ aspect GenerationBackend { ...@@ -258,7 +51,7 @@ aspect GenerationBackend {
tti.relationTargetsUnprocessed.put(node, true); tti.relationTargetsUnprocessed.put(node, true);
return node; return node;
} }
if (source == Source.INVISIBLE_PARENT || matches(getBuildConfig().typeIgnorePattern(), obj.getClass().getSimpleName())) { if (source == Source.INVISIBLE_PARENT || !isTypeEnabled(objClassName)) {
node.setInvisible(true); node.setInvisible(true);
} }
final ClassAnalysisResult car = analyzeClass(obj.getClass()); final ClassAnalysisResult car = analyzeClass(obj.getClass());
...@@ -266,7 +59,7 @@ aspect GenerationBackend { ...@@ -266,7 +59,7 @@ aspect GenerationBackend {
for (SingleChildMethod singleChildMethod : car.singleChildMethods()) { for (SingleChildMethod singleChildMethod : car.singleChildMethods()) {
Object target = singleChildMethod.getMethod().invoke(obj); Object target = singleChildMethod.getMethod().invoke(obj);
String childName = singleChildMethod.getName(); String childName = singleChildMethod.getName();
DumpNode targetNode = transform(tti, target, nextSource(source, matches(getBuildConfig().childIgnorePattern(), childName))); DumpNode targetNode = transform(tti, target, nextSource(source, !isChildEnabled(objClassName, childName)));
if (target != null && targetNode != null) { if (target != null && targetNode != null) {
DumpNormalChildNode normalChild = new DumpNormalChildNode(); DumpNormalChildNode normalChild = new DumpNormalChildNode();
normalChild.setName(childName); normalChild.setName(childName);
...@@ -281,7 +74,7 @@ aspect GenerationBackend { ...@@ -281,7 +74,7 @@ aspect GenerationBackend {
DumpListChildNode listChild = new DumpListChildNode(); DumpListChildNode listChild = new DumpListChildNode();
listChild.setComputed(listChildMethod.isNTAListChildMethod()); listChild.setComputed(listChildMethod.isNTAListChildMethod());
String childName = listChildMethod.getName(); String childName = listChildMethod.getName();
boolean shouldBeInvisisble = matches(getBuildConfig().childIgnorePattern(), childName); boolean shouldBeInvisisble = !isChildEnabled(objClassName, childName);
listChild.setName(childName); listChild.setName(childName);
for (Object target : targetList) { for (Object target : targetList) {
DumpNode targetNode = transform(tti, target, nextSource(source, shouldBeInvisisble)); DumpNode targetNode = transform(tti, target, nextSource(source, shouldBeInvisisble));
...@@ -354,6 +147,7 @@ aspect GenerationBackend { ...@@ -354,6 +147,7 @@ aspect GenerationBackend {
syn nta ClassAnalysisResult DumpAst.analyzeClass(java.lang.Class<?> clazz) { syn nta ClassAnalysisResult DumpAst.analyzeClass(java.lang.Class<?> clazz) {
ClassAnalysisResult result = new ClassAnalysisResult(); ClassAnalysisResult result = new ClassAnalysisResult();
String clazzName = clazz.getSimpleName();
for (java.lang.reflect.Method method : clazz.getMethods()) { for (java.lang.reflect.Method method : clazz.getMethods()) {
for (java.lang.annotation.Annotation annotation : method.getAnnotations()) { for (java.lang.annotation.Annotation annotation : method.getAnnotations()) {
String canonicalName = annotation.annotationType().getCanonicalName(); String canonicalName = annotation.annotationType().getCanonicalName();
...@@ -377,7 +171,7 @@ aspect GenerationBackend { ...@@ -377,7 +171,7 @@ aspect GenerationBackend {
normalSingleChildMethod.setName(optChildName); normalSingleChildMethod.setName(optChildName);
result.addAnalysedMethod(normalSingleChildMethod); result.addAnalysedMethod(normalSingleChildMethod);
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
System.err.println("Could not find getter for Opt-child " + optChildName + " in " + clazz.getName()); System.err.println("Could not find getter for Opt-child " + optChildName + " in " + clazzName);
throw new RuntimeException(e); throw new RuntimeException(e);
} }
break; break;
...@@ -396,7 +190,7 @@ aspect GenerationBackend { ...@@ -396,7 +190,7 @@ aspect GenerationBackend {
try { try {
java.lang.reflect.Method relationMethod = clazz.getMethod("get" + relationName); java.lang.reflect.Method relationMethod = clazz.getMethod("get" + relationName);
// normal get + token-name -> singleRelation // normal get + token-name -> singleRelation
if (!matches(getBuildConfig().relationIgnorePattern(), relationName)) { if (isRelationEnabled(clazzName, relationName)) {
SingleRelationMethod singleRelationMethod = new SingleRelationMethod(); SingleRelationMethod singleRelationMethod = new SingleRelationMethod();
singleRelationMethod.setMethod(relationMethod); singleRelationMethod.setMethod(relationMethod);
singleRelationMethod.setName(relationName); singleRelationMethod.setName(relationName);
...@@ -410,7 +204,7 @@ aspect GenerationBackend { ...@@ -410,7 +204,7 @@ aspect GenerationBackend {
try { try {
java.lang.reflect.Method relationMethod = clazz.getMethod("get" + relationName + "List"); java.lang.reflect.Method relationMethod = clazz.getMethod("get" + relationName + "List");
// normal get + token-name + "List" -> listRelation // normal get + token-name + "List" -> listRelation
if (!matches(getBuildConfig().relationIgnorePattern(), relationName)) { if (isRelationEnabled(clazzName, relationName)) {
ListRelationMethod listRelationMethod = new ListRelationMethod(); ListRelationMethod listRelationMethod = new ListRelationMethod();
listRelationMethod.setMethod(relationMethod); listRelationMethod.setMethod(relationMethod);
listRelationMethod.setName(relationName); listRelationMethod.setName(relationName);
...@@ -421,7 +215,7 @@ aspect GenerationBackend { ...@@ -421,7 +215,7 @@ aspect GenerationBackend {
// ignore, but we know this is probably not a relation at all // ignore, but we know this is probably not a relation at all
} }
} }
if (!matches(getBuildConfig().tokenIgnorePattern(), tokenName)) { if (isTokenEnabled(clazzName, tokenName)) {
IntrinsicTokenMethod tokenMethod = new IntrinsicTokenMethod(); IntrinsicTokenMethod tokenMethod = new IntrinsicTokenMethod();
tokenMethod.setMethod(method); tokenMethod.setMethod(method);
tokenMethod.setName(tokenName); tokenMethod.setName(tokenName);
...@@ -440,7 +234,7 @@ aspect GenerationBackend { ...@@ -440,7 +234,7 @@ aspect GenerationBackend {
if (attributeName.endsWith("List")) { if (attributeName.endsWith("List")) {
attributeName = attributeName.substring(0, attributeName.length() - 4); attributeName = attributeName.substring(0, attributeName.length() - 4);
} }
if (matches(getBuildConfig().ntaIncludePattern(), attributeName)) { if (isNonterminalAttributeEnabled(clazzName, attributeName)) {
if (Iterable.class.isAssignableFrom(method.getReturnType())) { if (Iterable.class.isAssignableFrom(method.getReturnType())) {
NTAListChildMethod ntaListChildMethod = new NTAListChildMethod(); NTAListChildMethod ntaListChildMethod = new NTAListChildMethod();
ntaListChildMethod.setMethod(method); ntaListChildMethod.setMethod(method);
...@@ -453,7 +247,7 @@ aspect GenerationBackend { ...@@ -453,7 +247,7 @@ aspect GenerationBackend {
result.addAnalysedMethod(ntaSingleChildMethod); result.addAnalysedMethod(ntaSingleChildMethod);
} }
} }
} else if (matches(getBuildConfig().attributeIncludePattern(), attributeName)) { } else if (isAttributeEnabled(clazzName, attributeName)) {
// normal attribute // normal attribute
AttributeMethod attributeMethod = new AttributeMethod(); AttributeMethod attributeMethod = new AttributeMethod();
attributeMethod.setMethod(method); attributeMethod.setMethod(method);
...@@ -475,12 +269,32 @@ aspect GenerationBackend { ...@@ -475,12 +269,32 @@ aspect GenerationBackend {
return Character.toUpperCase(s.charAt(0)) + s.substring(1); return Character.toUpperCase(s.charAt(0)) + s.substring(1);
} }
syn java.util.regex.Pattern BuildConfig.typeIgnorePattern() = java.util.regex.Pattern.compile(getTypeIgnore()); // TODO: add new attributes for: {token,child,relation,attribute,nta}Enabled(String parentType, String name). 1) just move implementation into this attribute. 2) add include/exclude on type-level to it.
syn java.util.regex.Pattern BuildConfig.childIgnorePattern() = java.util.regex.Pattern.compile(getChildIgnore()); syn boolean DumpAst.isTypeEnabled(String typeName) {
syn java.util.regex.Pattern BuildConfig.tokenIgnorePattern() = java.util.regex.Pattern.compile(getTokenIgnore()); return !matches(getBuildConfig().typeIgnorePattern(), typeName);
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 boolean DumpAst.isTokenEnabled(String parentType, String tokenName) {
syn java.util.regex.Pattern BuildConfig.relationIgnorePattern() = java.util.regex.Pattern.compile(getRelationIgnore()); return !matches(getBuildConfig().getGlobalPatternCollection().tokenIgnorePattern(), tokenName);
}
syn boolean DumpAst.isChildEnabled(String parentType, String childName) {
return !matches(getBuildConfig().getGlobalPatternCollection().childIgnorePattern(), childName);
}
syn boolean DumpAst.isRelationEnabled(String parentType, String relationName) {
return !matches(getBuildConfig().getGlobalPatternCollection().relationIgnorePattern(), relationName);
}
syn boolean DumpAst.isAttributeEnabled(String parentType, String attributeName) {
return matches(getBuildConfig().getGlobalPatternCollection().attributeIncludePattern(), attributeName);
}
syn boolean DumpAst.isNonterminalAttributeEnabled(String parentType, String ntaName) {
return matches(getBuildConfig().getGlobalPatternCollection().ntaIncludePattern(), ntaName);
}
syn java.util.regex.Pattern BuildConfig.typeIgnorePattern() = java.util.regex.Pattern.compile(getTypeIgnorePattern());
syn java.util.regex.Pattern PatternCollection.childIgnorePattern() = java.util.regex.Pattern.compile(getChildPattern());
syn java.util.regex.Pattern PatternCollection.tokenIgnorePattern() = java.util.regex.Pattern.compile(getTokenPattern());
syn java.util.regex.Pattern PatternCollection.attributeIncludePattern() = java.util.regex.Pattern.compile(getAttributePattern());
syn java.util.regex.Pattern PatternCollection.ntaIncludePattern() = java.util.regex.Pattern.compile(getNonterminalAttributePattern());
syn java.util.regex.Pattern PatternCollection.relationIgnorePattern() = java.util.regex.Pattern.compile(getRelationPattern());
static boolean ASTNode.matches(java.util.regex.Pattern p, String input) { static boolean ASTNode.matches(java.util.regex.Pattern p, String input) {
return p.matcher(input).matches(); return p.matcher(input).matches();
} }
......
aspect GenerationFrontend {
public class Dumper {
/**
* Prepare to read in the given object. Use the <code>dump*</code> methods to actually dump its content.
* @param obj the object to dump
* @return a builder to adjust dump options
*/
public static DumpBuilder read(Object obj) {
return new DumpBuilder(obj);
}
}
public enum SkinParamBooleanSetting {
/** Print in grayscale? */
Monochrome,
/** Use shadows? */
Shadowing,
/** Use handwritten style? */
Handwritten
}
public enum SkinParamStringSetting {
/** Set color of background */
backgroundColor
}
/**
* Building a dump.
* <p>
*
* <h3>Inclusion and Exclusion of Types</h3>
* Types can be only be disabled, see {@link #disableTypes(String[])}.
*
* <h3>Inclusion and Exclusion of Childrens, tokens and relations</h3>
* Childrens, tokens and relations are included by default.
* This can be changed using exclusions and inclusion, both in general and per-type.
* They are applied in the following order making later conditions take precedence over the first ones.
* <ol>
* <li>Include everything as default.
* <li>Exclude general.
* <li>Include per type.
* <li>Exclude per type.
* </ol>
*
* <h3>Inclusion and Exclusion of Attributes</h3>
* Attributes are excluded by default, i.e., not shown.
* This can be changed using inclusions and exclusions, both in general and per-type.
* They are applied in the following order making later conditions take precedence over the first ones.
* <ol>
* <li> Exclude everything as default.
* <li> Include general.
* <li> Exclude per type.
* <li> Include per type
* </ol>
*/
public class DumpBuilder {
private final Object target;
private String packageName;
private DumpAst result;
private final BuildConfig buildConfig;
private final PrintConfig printConfig;
protected DumpBuilder(Object target) {
this.target = target;
buildConfig = new BuildConfig();
buildConfig.setGlobalPatternCollection(new PatternCollection());
printConfig = new PrintConfig();
printConfig.setScale(1);
printConfig.setVersion(readVersion());
}
/**
* Add debug information in dumped content, mainly version numbers.
* @return this
*/
public DumpBuilder enableDebug() {
buildConfig.setDebug(true);
return this;
}
/**
* Include empty strings for all tokens
* @return this
*/
public DumpBuilder includeEmptyStringsOnTokens() {
buildConfig.setIncludeEmptyString(true);
return this;
}
/**
* Disable all objects with types matching at least one of the given regex strings.
* Disabled objects won't be included in any output. However, their children are still processed.
* <p>
* See {@link DumpBuilder} for details on inclusion and exclusion precedence.
* @param regexes patterns to match type names
* @return this
* @see java.util.regex.Pattern#compile(java.lang.String)
*/
public DumpBuilder disableTypes(String... regexes) {
updateRegexes(() -> buildConfig.getTypeIgnorePattern(),
s -> buildConfig.setTypeIgnorePattern(s),
regexes);
return this;
}
/**
* Exclude tokens and their value if the token name matches at least one of the given regex strings.
* <p>
* See {@link DumpBuilder} for details on inclusion and exclusion precedence.
* @param regexes regex patterns to match token names
* @return this
* @see java.util.regex.Pattern#compile(java.lang.String)
*/
public DumpBuilder excludeTokens(String... regexes) {
updateRegexes(() -> buildConfig.getGlobalPatternCollection().getTokenPattern(),
s -> buildConfig.getGlobalPatternCollection().setTokenPattern(s),
regexes);
return this;
}
/** TODO: document, implement, sort */
public DumpBuilder excludeTokensFor(String typeRegex, String... regexes) {
return this;
}
/** TODO: document, implement, sort */
public DumpBuilder excludeChildrenFor(String typeRegex, String... regexes) {
return this;
}
/** TODO: document, implement, sort */
public DumpBuilder excludeRelationsFor(String typeRegex, String... regexes) {
return this;
}
/** TODO: document, implement, sort */
public DumpBuilder excludeAttributesFor(String typeRegex, String... regexes) {
return this;
}
/** TODO: document, implement, sort */
public DumpBuilder excludeNonterminalAttributesFor(String typeRegex, String... regexes) {
return this;
}
/** TODO: document, implement, sort */
public DumpBuilder includeTokensFor(String typeRegex, String... regexes) {
return this;
}
/** TODO: document, implement, sort */
public DumpBuilder includeChildrenFor(String typeRegex, String... regexes) {
return this;
}
/** TODO: document, implement, sort */
public DumpBuilder includeRelationsFor(String typeRegex, String... regexes) {
return this;
}
/** TODO: document, implement, sort */
public DumpBuilder includeAttributesFor(String typeRegex, String... regexes) {
return this;
}
/** TODO: document, implement, sort */
public DumpBuilder includeNonterminalAttributesFor(String typeRegex, String... regexes) {
return this;
}
/**
* Include attributes (as tokens) and their value if the attribute name matches at least on of the given regex strings.
* <p>
* See {@link DumpBuilder} for details on inclusion and exclusion precedence.
* @param regexes regex patterns to match token names
* @return this
* @see java.util.regex.Pattern#compile(java.lang.String)
*/
public DumpBuilder includeAttributes(String... regexes) {
updateRegexes(() -> buildConfig.getGlobalPatternCollection().getAttributePattern(),
s -> buildConfig.getGlobalPatternCollection().setAttributePattern(s),
regexes);
return this;
}
/**
* Includes nonterminal-attributes (as children) and their values if
* their attribute name matches at least on of the given regex strings.
* <br>
* <b>Note</b>: A leading "get" and a trailing "List" in the name will be removed prior to matching.
* Thus, it should not be contained in the regex either.
* <p>
* See {@link DumpBuilder} for details on inclusion and exclusion precedence.
* @param regexes regex patterns to match token names
* @return this
* @see java.util.regex.Pattern#compile(java.lang.String)
*/
public DumpBuilder includeNonterminalAttributes(String... regexes) {
updateRegexes(() -> buildConfig.getGlobalPatternCollection().getNonterminalAttributePattern(),
s -> buildConfig.getGlobalPatternCollection().setNonterminalAttributePattern(s),
regexes);
return this;
}
/**
* Exclude every child whose name (i.e., context) matches at least on of the given regex strings.
* This means, that the complete object and its (transitive) children will never be included in any output.
* <p>
* See {@link DumpBuilder} for details on inclusion and exclusion precedence.
* @param regexes regex patterns to match child names
* @return this
* @see java.util.regex.Pattern#compile(java.lang.String)
*/
public DumpBuilder excludeChildren(String... regexes) {
updateRegexes(() -> buildConfig.getGlobalPatternCollection().getChildPattern(),
s -> buildConfig.getGlobalPatternCollection().setChildPattern(s),
regexes);
return this;
}
/**
* Exclude every relation whose role-name matches at least on of the given regex strings.
* 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.
* <p>
* See {@link DumpBuilder} for details on inclusion and exclusion precedence.
* @param regexes regex patterns to match child names
* @return this
* @see java.util.regex.Pattern#compile(java.lang.String)
*/
public DumpBuilder excludeRelations(String... regexes) {
updateRegexes(() -> buildConfig.getGlobalPatternCollection().getRelationPattern(),
s -> buildConfig.getGlobalPatternCollection().setRelationPattern(s),
regexes);
return this;
}
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);
} else {
setter.accept(getter.get() + "|" + value);
}
}
}
public DumpBuilder customPreamble(String option) {
printConfig.addHeader(new Header(option));
return this;
}
public DumpBuilder skinParam(SkinParamStringSetting setting, String value) {
customPreamble("skinparam " + setting.toString() + " " + value);
return this;
}
public DumpBuilder skinParam(SkinParamBooleanSetting setting, boolean value) {
customPreamble("skinparam " + setting.toString() + " " + value);
return this;
}
public DumpBuilder setScale(double value) {
printConfig.setScale(value);
return this;
}
private String readVersion() {
try {
java.util.ResourceBundle resources = java.util.ResourceBundle.getBundle("dumpAstVersion");
return resources.getString("version");
} catch (java.util.MissingResourceException e) {
return "version ?";
}
}
protected DumpAst build() {
if (result == null) {
result = new DumpAst();
result.setPackageName(this.packageName == null ? this.target.getClass().getPackage().getName() : this.packageName);
result.setBuildConfig(this.buildConfig);
result.setPrintConfig(this.printConfig);
try {
result.transform(new TransformationTransferInformation(), this.target);
} catch (java.lang.reflect.InvocationTargetException e) {
throw new RuntimeException("Could not transform :(", e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Could not transform :(", e);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Could not transform :(", e);
}
}
return result;
}
/**
* Write out content as plantuml source code.
* @param destination path of destination file
* @return this
* @throws java.io.IOException if an I/O error happend during opening or writing in that file
*/
public DumpBuilder dumpAsSource(java.nio.file.Path destination) throws java.io.IOException {
String content = build().toPlantUml();
try (java.io.Writer writer = java.nio.file.Files.newBufferedWriter(destination)) {
writer.write(content);
}
return this;
}
public DumpBuilder dumpAsYaml(java.nio.file.Path destination, boolean prependCreationComment) throws java.io.IOException {
String content = build().toYaml(prependCreationComment);
try (java.io.Writer writer = java.nio.file.Files.newBufferedWriter(destination)) {
writer.write(content);
}
return this;
}
}
}
...@@ -55,7 +55,6 @@ public class Compiler extends AbstractCompiler { ...@@ -55,7 +55,6 @@ public class Compiler extends AbstractCompiler {
} }
public static void main(String[] args) { public static void main(String[] args) {
System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
System.setProperty("mustache.debug", "true"); System.setProperty("mustache.debug", "true");
try { try {
new Compiler().run(args); new Compiler().run(args);
...@@ -96,7 +95,7 @@ public class Compiler extends AbstractCompiler { ...@@ -96,7 +95,7 @@ public class Compiler extends AbstractCompiler {
new BooleanOption("help", "Print usage and exit.") new BooleanOption("help", "Print usage and exit.")
.defaultValue(false)); .defaultValue(false));
optionVersion = addOption( optionVersion = addOption(
new BooleanOption("help", "Print version and exit.") new BooleanOption("version", "Print version and exit.")
.defaultValue(false)); .defaultValue(false));
optionVerbose = addOption( optionVerbose = addOption(
new BooleanOption("verbose", "Print more messages while compiling.") new BooleanOption("verbose", "Print more messages while compiling.")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment