You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2021/09/24 19:13:28 UTC
[plc4x] 01/04: fix: fix stackoverflow on type referencing each other
This is an automated email from the ASF dual-hosted git repository.
sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit 9470bbb3d6b06da665e3db7fe0e25c8f04e516db
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Sep 24 20:30:54 2021 +0200
fix: fix stackoverflow on type referencing each other
---
.../BaseFreemarkerLanguageTemplateHelper.java | 71 +++++++++++++---------
1 file changed, 42 insertions(+), 29 deletions(-)
diff --git a/code-generation/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/BaseFreemarkerLanguageTemplateHelper.java b/code-generation/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/BaseFreemarkerLanguageTemplateHelper.java
index 286da39..e494acd 100644
--- a/code-generation/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/BaseFreemarkerLanguageTemplateHelper.java
+++ b/code-generation/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/BaseFreemarkerLanguageTemplateHelper.java
@@ -23,12 +23,8 @@ import net.objecthunter.exp4j.ExpressionBuilder;
import org.apache.plc4x.plugins.codegenerator.types.definitions.*;
import org.apache.plc4x.plugins.codegenerator.types.enums.EnumValue;
import org.apache.plc4x.plugins.codegenerator.types.fields.*;
-import org.apache.plc4x.plugins.codegenerator.types.references.ComplexTypeReference;
-import org.apache.plc4x.plugins.codegenerator.types.references.SimpleTypeReference;
-import org.apache.plc4x.plugins.codegenerator.types.references.StringTypeReference;
-import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
+import org.apache.plc4x.plugins.codegenerator.types.references.*;
import org.apache.plc4x.plugins.codegenerator.types.terms.*;
-import org.w3c.dom.Node;
import java.util.*;
import java.util.stream.Collectors;
@@ -199,13 +195,18 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
* @return collection of complex type references used in the type.
*/
public Collection<String> getComplexTypeReferences(TypeDefinition baseType) {
- Set<String> complexTypeReferences = new HashSet<>();
+ return getComplexTypeReferences(baseType, new HashSet<>());
+ }
+
+ public Collection<String> getComplexTypeReferences(TypeDefinition baseType, Set<String> complexTypeReferences) {
+ // We add ourselves to avoid a stackoverflow
+ complexTypeReferences.add(baseType.getName());
// If this is a subtype of a discriminated type, we have to add a reference to the parent type.
if (baseType instanceof DiscriminatedComplexTypeDefinition) {
DiscriminatedComplexTypeDefinition discriminatedComplexTypeDefinition = (DiscriminatedComplexTypeDefinition) baseType;
if (!discriminatedComplexTypeDefinition.isAbstract()) {
- complexTypeReferences.add(((ComplexTypeReference)
- discriminatedComplexTypeDefinition.getParentType().getTypeReference()).getName());
+ String typeReferenceName = ((ComplexTypeReference) discriminatedComplexTypeDefinition.getParentType().getTypeReference()).getName();
+ complexTypeReferences.add(typeReferenceName);
}
}
// If it's a complex type definition, add all the types referenced by any property fields
@@ -222,13 +223,14 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
} else if (field instanceof SwitchField) {
SwitchField switchField = (SwitchField) field;
for (DiscriminatedComplexTypeDefinition switchCase : switchField.getCases()) {
- complexTypeReferences.addAll(getComplexTypeReferences(switchCase));
+ if (complexTypeReferences.contains(switchCase.getName())) {
+ continue;
+ }
+ complexTypeReferences.addAll(getComplexTypeReferences(switchCase, complexTypeReferences));
}
}
}
- }
- // In case this is a enum type, we have to check all the constant types.
- else if (baseType instanceof EnumTypeDefinition) {
+ } else if (baseType instanceof EnumTypeDefinition) {// In case this is an enum type, we have to check all the constant types.
for (String constantName : ((EnumTypeDefinition) baseType).getConstantNames()) {
final TypeReference constantType = ((EnumTypeDefinition) thisType).getConstantType(constantName);
if (constantType instanceof ComplexTypeReference) {
@@ -246,6 +248,9 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
}
}
}
+
+ // We remove ourselves to avoid a stackoverflow
+ complexTypeReferences.remove(baseType.getName());
return complexTypeReferences;
}
@@ -323,13 +328,13 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
if (!(typeReference instanceof ComplexTypeReference)) {
throw new FreemarkerException("type reference for enum types must be of type complex type");
}
- ComplexTypeReference complexTypeReference = (ComplexTypeReference) typeReference;
- final TypeDefinition typeDefinition = types.get(complexTypeReference.getName());
+ String typeName = ((ComplexTypeReference) typeReference).getName();
+ final TypeDefinition typeDefinition = types.get(typeName);
if (typeDefinition == null) {
- throw new FreemarkerException("Couldn't find given enum type definition with name " + complexTypeReference.getName());
+ throw new FreemarkerException("Couldn't find given enum type definition with name " + typeName);
}
if (!(typeDefinition instanceof EnumTypeDefinition)) {
- throw new FreemarkerException("Referenced type with name " + complexTypeReference.getName() + " is not an enum type");
+ throw new FreemarkerException("Referenced type with name " + typeName + " is not an enum type");
}
EnumTypeDefinition enumTypeDefinition = (EnumTypeDefinition) typeDefinition;
// Enum types always have simple type references.
@@ -368,7 +373,11 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
if (!(getThisTypeDefinition() instanceof ComplexTypeDefinition)) {
return null;
}
- return ((ComplexTypeDefinition) getThisTypeDefinition()).getAllPropertyFields()
+ return getAllPropertyFields((ComplexTypeDefinition) getThisTypeDefinition(), fieldName);
+ }
+
+ public PropertyField getAllPropertyFields(ComplexTypeDefinition complexTypeDefinition, String fieldName) {
+ return complexTypeDefinition.getAllPropertyFields()
.stream()
.filter(propertyField -> propertyField.getName().equals(fieldName))
.findFirst()
@@ -379,7 +388,11 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
if (!(getThisTypeDefinition() instanceof ComplexTypeDefinition)) {
return null;
}
- return ((ComplexTypeDefinition) getThisTypeDefinition()).getPropertyFields()
+ return getPropertyField((ComplexTypeDefinition) getThisTypeDefinition(), fieldName);
+ }
+
+ public PropertyField getPropertyField(ComplexTypeDefinition complexTypeDefinition, String fieldName) {
+ return complexTypeDefinition.getPropertyFields()
.stream()
.filter(propertyField -> propertyField.getName().equals(fieldName))
.findFirst()
@@ -696,8 +709,8 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
* @return true if a field with the given name already exists in the same type.
*/
public boolean isNonDiscriminatorField(String discriminatorName) {
- return ((ComplexTypeDefinition) thisType).getAllPropertyFields().stream().anyMatch(
- field -> !(field instanceof DiscriminatorField) && field.getName().equals(discriminatorName));
+ return ((ComplexTypeDefinition) thisType).getAllPropertyFields().stream()
+ .anyMatch(field -> !(field instanceof DiscriminatorField) && field.getName().equals(discriminatorName));
}
/**
@@ -711,8 +724,8 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
public boolean isDiscriminatorField(String discriminatorName) {
List<String> names = getDiscriminatorNames();
if (names != null) {
- return getDiscriminatorNames().stream().anyMatch(
- field -> field.equals(discriminatorName));
+ return getDiscriminatorNames().stream()
+ .anyMatch(field -> field.equals(discriminatorName));
}
return false;
}
@@ -844,7 +857,7 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
}
TypeDefinition complexTypeDefinition = getTypeDefinitions().get(complexTypeReference.getName());
if (complexTypeDefinition.getParserArguments().length <= index) {
- throw new FreemarkerException("Type " + complexTypeReference.getName() + " specifies too few parser arguments");
+ throw new FreemarkerException("Type " + complexTypeReference.getName() + " specifies too few parser arguments. Available:" + complexTypeDefinition.getParserArguments().length + " index:" + index);
}
return complexTypeDefinition.getParserArguments()[index].getType();
}
@@ -1001,16 +1014,16 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
* Confirms if a variable is an virtual variable. These need to be handled differently when serializing and parsing.
*
* @param vl The variable to search for.
- * @return boolean returns true if the variable's name is an vritual field
+ * @return boolean returns true if the variable's name is an virtual field
*/
protected boolean isVariableLiteralVirtualField(VariableLiteral vl) {
- List<Field> fields = null;
+ List<Field> fields = new ArrayList<>();
if (thisType instanceof ComplexTypeDefinition) {
ComplexTypeDefinition complexType = (ComplexTypeDefinition) getThisTypeDefinition();
- fields = complexType.getFields();
- }
- if (fields == null) {
- return false;
+ fields.addAll(complexType.getFields());
+ if (complexType.getParentType() != null) {
+ fields.addAll(((ComplexTypeDefinition) complexType.getParentType()).getFields());
+ }
}
for (Field field : fields) {
if (field.getTypeName().equals(VIRTUAL)) {