Skip to content

Commit 58864f9

Browse files
committed
Add generic list handling for AST node attributes nodes and builders
1 parent 58e2927 commit 58864f9

File tree

9 files changed

+236
-23
lines changed

9 files changed

+236
-23
lines changed

monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,19 @@ public boolean isListType(String type) {
8787
|| "ArrayList".equals(type) || "java.util.ArrayList".equals(type);
8888
}
8989

90+
public boolean isArrayType(String type) {
91+
return type.endsWith("[]");
92+
}
93+
94+
public boolean isCollectionType(String type){
95+
int index = type.indexOf('<');
96+
if (index != -1) {
97+
type = type.substring(0, index);
98+
}
99+
return "Collection".equals(type) || "java.util.Collection".equals(type)
100+
|| "ArrayList".equals(type) || "java.util.ArrayList".equals(type);
101+
}
102+
90103
public boolean isMapType(String type) {
91104
int index = type.indexOf('<');
92105
if (index != -1) {

monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderListMutatorDecorator.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* (c) https://github.com/MontiCore/monticore */
22
package de.monticore.codegen.cd2java._ast.builder.buildermethods;
33

4+
import de.monticore.cd4code.CD4CodeMill;
45
import de.monticore.cdbasis._ast.ASTCDAttribute;
56
import de.monticore.cd4codebasis._ast.ASTCDMethod;
67
import de.monticore.cd4codebasis._ast.ASTCDParameter;
@@ -10,6 +11,7 @@
1011
import de.monticore.types.mcbasictypes._ast.ASTMCReturnType;
1112
import de.monticore.types.mcbasictypes._ast.ASTMCType;
1213
import de.monticore.types.mcbasictypes.MCBasicTypesMill;
14+
import de.monticore.types.mcsimplegenerictypes._ast.ASTMCBasicGenericType;
1315

1416
import java.util.List;
1517
import java.util.stream.Collectors;
@@ -46,8 +48,23 @@ protected List<ASTCDMethod> createSetter(ASTCDAttribute attribute) {
4648
String parameterCall = m.getCDParameterList().stream()
4749
.map(ASTCDParameter::getName)
4850
.collect(Collectors.joining(", "));
49-
this.replaceTemplate(EMPTY_BODY, m, new TemplateHookPoint("_ast.builder.MethodDelegate4ASTBuilder",
50-
attribute, methodName, parameterCall));
51+
52+
List<ASTCDParameter> parameters = m.getCDParameterList();
53+
String castType = "";
54+
if (parameters != null && !parameters.isEmpty()) {
55+
ASTMCType lastParameterType = parameters.get(parameters.size() - 1).getMCType();
56+
if(attribute.getMCType() instanceof ASTMCBasicGenericType && lastParameterType.printType().equals(((ASTMCBasicGenericType)attribute.getMCType()).getMCTypeArgument(0).printType())){
57+
castType = "List<" + lastParameterType.printType() + ">";
58+
}
59+
if(attribute.getMCType().printType().startsWith("UnaryOperator")){
60+
System.out.println(attribute.getMCType().printType());
61+
}
62+
}
63+
64+
65+
66+
this.replaceTemplate(EMPTY_BODY, m, new TemplateHookPoint("builder.MethodDelegate4ASTBuilderGeneric",
67+
attribute, methodName, parameterCall, castType));
5168
}
5269
return methods;
5370
}
@@ -58,7 +75,7 @@ protected ASTCDMethod createSetListMethod(ASTCDAttribute ast) {
5875
ASTCDMethod method = this.getCDMethodFacade().createMethodByDefinition(signature);
5976
ASTMCReturnType returnType = MCBasicTypesMill.mCReturnTypeBuilder().setMCType(builderType).build();
6077
method.setMCReturnType(returnType);
61-
this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("_ast.builder.Set4ASTBuilder", ast));
78+
this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("builder.Set4ASTBuilderGeneric", ast));
6279
return method;
6380
}
6481
}

monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
import de.monticore.codegen.mc2cd.MC2CDStereotypes;
1010
import de.monticore.generating.templateengine.GlobalExtensionManagement;
1111
import de.monticore.generating.templateengine.HookPoint;
12+
import de.monticore.generating.templateengine.StringHookPoint;
1213
import de.monticore.generating.templateengine.TemplateHookPoint;
1314
import de.monticore.types.mcbasictypes._ast.ASTMCType;
1415
import org.apache.commons.lang3.StringUtils;
15-
1616
import java.util.List;
1717
import java.util.stream.Collectors;
1818

@@ -42,11 +42,19 @@ public List<ASTCDMethod> decorate(final ASTCDAttribute ast) {
4242
}
4343
this.attributeType = getAttributeType(ast);
4444

45-
List<ASTCDMethod> methods = getMethodSignatures().stream()
46-
.map(getCDMethodFacade()::createMethodByDefinition)
47-
.collect(Collectors.toList());
45+
List<ASTCDMethod> methods;
46+
boolean isGeneric = getDecorationHelper().isAstNode(ast);
47+
if (isGeneric) {
48+
methods = getMethodSignaturesGeneric().stream()
49+
.map(getCDMethodFacade()::createMethodByDefinition)
50+
.collect(Collectors.toList());
51+
} else {
52+
methods = getMethodSignatures().stream()
53+
.map(getCDMethodFacade()::createMethodByDefinition)
54+
.collect(Collectors.toList());
55+
}
4856

49-
methods.forEach(m -> this.replaceTemplate(EMPTY_BODY, m, createListImplementation(m)));
57+
methods.forEach(m -> this.replaceTemplate(EMPTY_BODY, m, createListImplementation(m,isGeneric)));
5058
return methods;
5159
}
5260

@@ -60,22 +68,46 @@ protected boolean hasDerivedAttributeName(ASTCDAttribute astcdAttribute) {
6068

6169
protected abstract List<String> getMethodSignatures();
6270

71+
protected abstract List<String> getMethodSignaturesGeneric();
72+
6373
protected String getTypeArgumentFromListType(ASTMCType type) {
6474
String typeString = CD4CodeMill.prettyPrint(type, false);
6575
int lastListIndex = typeString.lastIndexOf("List<") + 5;
6676
return typeString.substring(lastListIndex, typeString.length() - 1);
6777
}
6878

69-
protected HookPoint createListImplementation(final ASTCDMethod method) {
79+
protected HookPoint createListImplementation(final ASTCDMethod method, boolean isGeneric) {
80+
String errorCode = "0Xdsidusd";
7081
String attributeName = StringUtils.uncapitalize(capitalizedAttributeNameWithOutS);
7182
int attributeIndex = method.getName().lastIndexOf(capitalizedAttributeNameWithOutS);
7283
String methodName = method.getName().substring(0, attributeIndex);
7384
String parameterCall = method.getCDParameterList().stream()
7485
.map(ASTCDParameter::getName)
7586
.collect(Collectors.joining(", "));
76-
String returnType = CD4CodeMill.prettyPrint(method.getMCReturnType(), false);
7787

78-
return new TemplateHookPoint("methods.MethodDelegate", attributeName, methodName, parameterCall, returnType);
88+
List<ASTCDParameter> parameters = method.getCDParameterList();
89+
ASTMCType lastParameterType = null;
90+
if (parameters != null && !parameters.isEmpty()) {
91+
lastParameterType = parameters.get(parameters.size() - 1).getMCType();
92+
}
93+
94+
//TODO this is bad and should not be merged in this state
95+
String returnType = CD4CodeMill.prettyPrint(method.getMCReturnType(), false);
96+
if(isGeneric) {
97+
String parameterAttribute = parameterCall.split(", ")[parameterCall.split(", ").length-1];
98+
String parameterType="";
99+
if(lastParameterType != null && (getDecorationHelper().isListType(lastParameterType.printType()) || getDecorationHelper().isCollectionType(lastParameterType.printType()))){
100+
parameterType = "Collection";
101+
}
102+
if(lastParameterType != null && getDecorationHelper().isArrayType(lastParameterType.printType())){
103+
parameterType = "Array";
104+
}
105+
106+
return new TemplateHookPoint("mc.methods.ListMethodDelegate", attributeName, methodName, parameterCall, returnType, attributeType, parameterType, parameterAttribute, errorCode);
107+
108+
}else{
109+
return new TemplateHookPoint("methods.MethodDelegate", attributeName, methodName, parameterCall, returnType);
110+
}
79111
}
80112

81113
public String getCapitalizedAttributeNameWithS(ASTCDAttribute attribute) {

monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,39 @@
66
import de.monticore.codegen.cd2java.methods.ListMethodDecorator;
77
import de.monticore.generating.templateengine.GlobalExtensionManagement;
88
import de.monticore.generating.templateengine.TemplateHookPoint;
9-
109
import java.util.Arrays;
1110
import java.util.List;
12-
1311
import static de.monticore.cd.codegen.CD2JavaTemplates.EMPTY_BODY;
1412

1513
public class ListAccessorDecorator extends ListMethodDecorator {
1614

1715
protected static final String GET_LIST = "public List<%s> get%sList();";
16+
protected static final String GET_LIST_GENERIC = "public List<? extends %s> get%sList();";
1817
protected static final String CONTAINS = "public boolean contains%s(Object element);";
1918
protected static final String CONTAINS_ALL = "public boolean containsAll%s(Collection<?> collection);";
2019
protected static final String IS_EMPTY = "public boolean isEmpty%s();";
2120
protected static final String ITERATOR = "public Iterator<%s> iterator%s();";
21+
protected static final String ITERATOR_GENERIC = "public Iterator<? extends %s> iterator%s();";
2222
protected static final String SIZE = "public int size%s();";
2323
protected static final String TO_ARRAY = "public %s[] toArray%s(%s[] array);";
2424
protected static final String TO_ARRAY_ = "public Object[] toArray%s();";
2525
protected static final String SPLITERATOR = "public Spliterator<%s> spliterator%s();";
26+
protected static final String SPLITERATOR_GENERIC = "public Spliterator<? extends %s> spliterator%s();";
2627
protected static final String STREAM = "public Stream<%s> stream%s();";
28+
protected static final String STREAM_GENERIC = "public Stream<? extends %s> stream%s();";
2729
protected static final String PARALLEL_STREAM = "public Stream<%s> parallelStream%s();";
30+
protected static final String PARALLEL_STREAM_GENERIC = "public Stream<? extends %s> parallelStream%s();";
2831
protected static final String GET = "public %s get%s(int index);";
2932
protected static final String INDEX_OF = "public int indexOf%s(Object element);";
3033
protected static final String LAST_INDEX_OF = "public int lastIndexOf%s(Object element);";
3134
protected static final String EQUALS = "public boolean equals%s(Object o);";
3235
protected static final String HASHCODE = "public int hashCode%s();";
3336
protected static final String LIST_ITERATOR = "public ListIterator<%s> listIterator%s();";
37+
protected static final String LIST_ITERATOR_GENERIC = "public ListIterator<? extends %s> listIterator%s();";
3438
protected static final String LIST_ITERATOR_ = "public ListIterator<%s> listIterator%s(int index);";
39+
protected static final String LIST_ITERATOR_GENERIC_ = "public ListIterator<?extends %s> listIterator%s(int index);";
3540
protected static final String SUBLIST = "public List<%s> subList%s(int start, int end);";
41+
protected static final String SUBLIST_GENERIC = "public List<? extends %s> subList%s(int start, int end);";
3642

3743
public ListAccessorDecorator(final GlobalExtensionManagement glex) {
3844
super(glex);
@@ -47,10 +53,18 @@ public List<ASTCDMethod> decorate(ASTCDAttribute ast) {
4753

4854

4955
protected ASTCDMethod createGetListMethod(ASTCDAttribute ast) {
50-
String signature = String.format(GET_LIST, attributeType, capitalizedAttributeNameWithOutS);
51-
ASTCDMethod getList = this.getCDMethodFacade().createMethodByDefinition(signature);
52-
this.replaceTemplate(EMPTY_BODY, getList, new TemplateHookPoint("methods.Get", ast));
53-
return getList;
56+
if (getDecorationHelper().isAstNode(ast)) {
57+
String signature = String.format(GET_LIST_GENERIC, attributeType, capitalizedAttributeNameWithOutS);
58+
ASTCDMethod getList = this.getCDMethodFacade().createMethodByDefinition(signature);
59+
this.replaceTemplate(EMPTY_BODY, getList, new TemplateHookPoint("methods.Get", ast));
60+
return getList;
61+
} else {
62+
String signature = String.format(GET_LIST, attributeType, capitalizedAttributeNameWithOutS);
63+
ASTCDMethod getList = this.getCDMethodFacade().createMethodByDefinition(signature);
64+
this.replaceTemplate(EMPTY_BODY, getList, new TemplateHookPoint("methods.Get", ast));
65+
return getList;
66+
}
67+
5468
}
5569

5670
@Override
@@ -76,4 +90,28 @@ protected List<String> getMethodSignatures() {
7690
String.format(SUBLIST, attributeType, capitalizedAttributeNameWithS)
7791
);
7892
}
79-
}
93+
94+
@Override
95+
protected List<String> getMethodSignaturesGeneric() {
96+
return Arrays.asList(
97+
String.format(CONTAINS, capitalizedAttributeNameWithOutS),
98+
String.format(CONTAINS_ALL, capitalizedAttributeNameWithS),
99+
String.format(IS_EMPTY, capitalizedAttributeNameWithS),
100+
String.format(ITERATOR_GENERIC, attributeType, capitalizedAttributeNameWithS),
101+
String.format(SIZE, capitalizedAttributeNameWithS),
102+
String.format(TO_ARRAY, attributeType, capitalizedAttributeNameWithS, attributeType),
103+
String.format(TO_ARRAY_, capitalizedAttributeNameWithS),
104+
String.format(SPLITERATOR_GENERIC, attributeType, capitalizedAttributeNameWithS),
105+
String.format(STREAM_GENERIC, attributeType, capitalizedAttributeNameWithS),
106+
String.format(PARALLEL_STREAM_GENERIC, attributeType, capitalizedAttributeNameWithS),
107+
String.format(GET, attributeType, capitalizedAttributeNameWithOutS),
108+
String.format(INDEX_OF, capitalizedAttributeNameWithOutS),
109+
String.format(LAST_INDEX_OF, capitalizedAttributeNameWithOutS),
110+
String.format(EQUALS, capitalizedAttributeNameWithS),
111+
String.format(HASHCODE, capitalizedAttributeNameWithS),
112+
String.format(LIST_ITERATOR_GENERIC, attributeType, capitalizedAttributeNameWithS),
113+
String.format(LIST_ITERATOR_GENERIC_, attributeType, capitalizedAttributeNameWithS),
114+
String.format(SUBLIST_GENERIC, attributeType, capitalizedAttributeNameWithS)
115+
);
116+
}
117+
}

monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
public class ListMutatorDecorator extends ListMethodDecorator {
1616

1717
protected static final String SET_LIST = "public void set%sList(List<%s> %s);";
18+
protected static final String SET_LIST_GENERIC = "public void set%sList(List<? extends %s> %s);";
1819
protected static final String CLEAR = "public void clear%s();";
1920
protected static final String ADD = "public boolean add%s(%s element);";
2021
protected static final String ADD_ALL = "public boolean addAll%s(Collection<? extends %s> collection);";
@@ -42,13 +43,21 @@ public List<ASTCDMethod> decorate(ASTCDAttribute ast) {
4243
}
4344

4445
protected ASTCDMethod createSetListMethod(ASTCDAttribute ast) {
45-
String signature = String.format(SET_LIST, capitalizedAttributeNameWithOutS, attributeType, ast.getName());
46-
ASTCDMethod getList = this.getCDMethodFacade().createMethodByDefinition(signature);
47-
this.replaceTemplate(EMPTY_BODY, getList, new TemplateHookPoint("methods.Set", ast));
48-
return getList;
46+
String errorCode = "0X23232";
47+
if(getDecorationHelper().isAstNode(ast)){
48+
String signature = String.format(SET_LIST_GENERIC, capitalizedAttributeNameWithOutS, attributeType, ast.getName());
49+
ASTCDMethod setListMethod = getCDMethodFacade().createMethodByDefinition(signature);
50+
this.replaceTemplate(EMPTY_BODY, setListMethod, new TemplateHookPoint("mc.methods.ListSetGeneric", ast, ast.getMCType().printType(), errorCode));
51+
return setListMethod;
52+
}else{
53+
String signature = String.format(SET_LIST, capitalizedAttributeNameWithOutS, attributeType, ast.getName());
54+
ASTCDMethod setListMethod = getCDMethodFacade().createMethodByDefinition(signature);
55+
this.replaceTemplate(EMPTY_BODY, setListMethod, new TemplateHookPoint("methods.Set", ast));
56+
return setListMethod;
57+
}
4958
}
5059

51-
protected List<ASTCDMethod> createSetter(ASTCDAttribute ast){
60+
protected List<ASTCDMethod> createSetter(ASTCDAttribute ast) {
5261
return super.decorate(ast);
5362
}
5463

@@ -72,4 +81,24 @@ protected List<String> getMethodSignatures() {
7281
String.format(SORT, capitalizedAttributeNameWithS, attributeType)
7382
);
7483
}
84+
85+
@Override
86+
protected List<String> getMethodSignaturesGeneric() {
87+
return Arrays.asList(
88+
String.format(CLEAR, capitalizedAttributeNameWithS),
89+
String.format(ADD, capitalizedAttributeNameWithOutS, attributeType),
90+
String.format(ADD_ALL, capitalizedAttributeNameWithS, attributeType),
91+
String.format(REMOVE, capitalizedAttributeNameWithOutS),
92+
String.format(REMOVE_ALL, capitalizedAttributeNameWithS),
93+
String.format(RETAIN_ALL, capitalizedAttributeNameWithS),
94+
String.format(REMOVE_IF, capitalizedAttributeNameWithOutS, attributeType),
95+
String.format(FOR_EACH, capitalizedAttributeNameWithS, attributeType),
96+
String.format(ADD_, capitalizedAttributeNameWithOutS, attributeType),
97+
String.format(ADD_ALL_, capitalizedAttributeNameWithS, attributeType),
98+
String.format(REMOVE_, attributeType, capitalizedAttributeNameWithOutS),
99+
String.format(SET, attributeType, capitalizedAttributeNameWithOutS, attributeType),
100+
String.format(REPLACE_ALL, capitalizedAttributeNameWithS, attributeType),
101+
String.format(SORT, capitalizedAttributeNameWithS, attributeType)
102+
);
103+
}
75104
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<#-- (c) https://github.com/MontiCore/monticore -->
2+
${tc.signature("attribute", "methodName", "paramCall","castType")}
3+
<#assign genHelper = glex.getGlobalVar("astHelper")>
4+
<#if castType?has_content>((${castType})</#if>this.${genHelper.getPlainGetter(attribute)}()<#if castType?has_content>)</#if>.${methodName}(${paramCall});
5+
return this.realBuilder;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<#-- (c) https://github.com/MontiCore/monticore -->
2+
${tc.signature("attribute")}
3+
this.${attribute.getName()} = ${attribute.getName()};
4+
return this.realBuilder;
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<#-- (c) https://github.com/MontiCore/monticore -->
2+
${tc.signature("attributeName", "methodName", "paramCall", "returnType","attributeType","parameterType","parameterAttribute","errorCode")}
3+
<#if paramCall?has_content && parameterType == "Collection" || parameterType == "Array">
4+
<#if parameterType == "Collection">
5+
<#-- when the argument is a Collection we only need to check every argument -->
6+
boolean allElementsValid = true;
7+
if(${parameterAttribute} != null) {
8+
for(Object elementOf${attributeName}: ${parameterAttribute}) {
9+
if(!(elementOf${attributeName} instanceof ${attributeType})){
10+
allElementsValid = false;
11+
break;
12+
}
13+
}
14+
}
15+
16+
if(allElementsValid) {
17+
<#if returnType != "void">return </#if>((List<${attributeType}>)this.get${attributeName?cap_first}List()).${methodName}(${paramCall});
18+
}else{
19+
Log.error("${errorCode} a unexpected type was set in the a method created with the ListMethodDelegate.ftl");
20+
<#if returnType != "void">return </#if>((List<${attributeType}>)this.get${attributeName?cap_first}List()).${methodName}(${paramCall});
21+
}
22+
<#-- when the argument is not a list we only need to check the argument -->
23+
<#elseif parameterType == "Array">
24+
boolean allElementsValid = true;
25+
if(${parameterAttribute} != null) {
26+
for(Object elementOf${attributeName} : ${parameterAttribute}) {
27+
if(!(elementOf${attributeName} instanceof ${attributeType})){
28+
allElementsValid = false;
29+
break;
30+
}
31+
}
32+
}
33+
34+
if(allElementsValid) {
35+
<#if returnType != "void">return </#if>((List<${attributeType}>)this.get${attributeName?cap_first}List()).${methodName}(${paramCall});
36+
}else{
37+
Log.error("${errorCode} a unexpected type was set in the method created with the ArrayMethodDelegate.ftl");
38+
<#if returnType != "void">return </#if>((List<${attributeType}>)this.get${attributeName?cap_first}List()).${methodName}(${paramCall});
39+
}
40+
41+
<#else>
42+
if(${parameterAttribute} instanceof ${attributeType}){
43+
<#if returnType != "void">return </#if>((List<${attributeType}>)this.get${attributeName?cap_first}List()).${methodName}(${paramCall});
44+
}else{
45+
Log.error("${errorCode} a unexpected type was set in the a method created with the ListMethodDelegate.ftl");
46+
<#if returnType != "void">return </#if>((List<${attributeType}>)this.get${attributeName?cap_first}List()).${methodName}(${paramCall});
47+
}
48+
</#if>
49+
50+
<#else>
51+
<#if returnType != "void">return </#if>((List<${attributeType}>)this.get${attributeName?cap_first}List()).${methodName}(${paramCall});
52+
</#if>
53+

0 commit comments

Comments
 (0)