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/17 18:40:45 UTC

[plc4x] 04/08: feat(plc4x/codegen): virtual fields should now work much better

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 8cc4e450ef186c7557bfcb991f24dc9f4019cf61
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Sep 17 20:30:10 2021 +0200

    feat(plc4x/codegen): virtual fields should now work much better
    
    + plc4go: changed enums to be always a non pointer (A enum is immutable so copying should be no issue)
    + added initial traces to codegen for java and golang
---
 .../BaseFreemarkerLanguageTemplateHelper.java      | 54 ++++++++++++++++++
 .../language/go/GoLanguageTemplateHelper.java      | 64 +++++++++++++++-------
 .../resources/templates/go/model-template.go.ftlh  | 24 ++++----
 .../templates/go/parser-factory-template.go.ftlh   |  2 +-
 .../go/xml-parser-factory-template.go.ftlh         |  2 +-
 .../language/java/JavaLanguageTemplateHelper.java  | 31 ++++++-----
 .../templates/java/pojo-template.java.ftlh         |  4 +-
 .../internal/plc4go/ads/readwrite/ParserHelper.go  |  2 +-
 .../plc4go/ads/readwrite/XmlParserHelper.go        |  2 +-
 .../internal/plc4go/ads/readwrite/model/AdsData.go | 42 +++++++-------
 .../ads/readwrite/model/AdsReadWriteRequest.go     |  6 +-
 .../plc4go/ads/readwrite/model/AmsPacket.go        |  2 +-
 .../plc4go/knxnetip/readwrite/ParserHelper.go      |  2 +-
 .../plc4go/knxnetip/readwrite/XmlParserHelper.go   |  2 +-
 .../model/ApduDataDeviceDescriptorResponse.go      |  4 +-
 .../readwrite/model/ApduDataGroupValueResponse.go  |  4 +-
 .../readwrite/model/ApduDataGroupValueWrite.go     |  4 +-
 .../knxnetip/readwrite/model/ComObjectTable.go     |  8 +--
 .../plc4go/s7/readwrite/model/COTPPacket.go        |  2 +-
 .../plc4go/s7/readwrite/model/S7Message.go         |  4 +-
 .../s7/readwrite/model/S7VarPayloadDataItem.go     | 14 ++---
 21 files changed, 180 insertions(+), 99 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 34ddb55..286da39 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
@@ -49,6 +49,8 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
     public static final String START_POS = "startPos";
     public static final String LAST_ITEM = "lastItem";
     public static final String IMPLICIT = "implicit";
+    public static final String VIRTUAL = "virtual";
+    public static final String DISCRIMINATOR = "discriminator";
 
     static {
         builtInFields = new HashMap<>();
@@ -996,6 +998,58 @@ 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
+     */
+    protected boolean isVariableLiteralVirtualField(VariableLiteral vl) {
+        List<Field> fields = null;
+        if (thisType instanceof ComplexTypeDefinition) {
+            ComplexTypeDefinition complexType = (ComplexTypeDefinition) getThisTypeDefinition();
+            fields = complexType.getFields();
+        }
+        if (fields == null) {
+            return false;
+        }
+        for (Field field : fields) {
+            if (field.getTypeName().equals(VIRTUAL)) {
+                VirtualField virtualField = (VirtualField) field;
+                if (vl.getName().equals(virtualField.getName())) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Confirms if a variable is an discriminator 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 discriminator field
+     */
+    protected boolean isVariableLiteralDiscriminatorField(VariableLiteral vl) {
+        List<Field> fields = null;
+        if (thisType instanceof ComplexTypeDefinition) {
+            ComplexTypeDefinition complexType = (ComplexTypeDefinition) getThisTypeDefinition();
+            fields = complexType.getFields();
+        }
+        if (fields == null) {
+            return false;
+        }
+        for (Field field : fields) {
+            if (field.getTypeName().equals(DISCRIMINATOR)) {
+                DiscriminatorField discriminatorField = (DiscriminatorField) field;
+                if (vl.getName().equals(discriminatorField.getName())) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
      * Returns the implicit field that has the same name as the variable. These need to be handled differently when serializing and parsing.
      *
      * @param vl The variable to search for.
diff --git a/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java b/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java
index 40e3065..86b11c6 100644
--- a/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java
+++ b/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java
@@ -21,6 +21,7 @@ package org.apache.plc4x.language.go;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.math.NumberUtils;
 import org.apache.plc4x.plugins.codegenerator.protocol.freemarker.BaseFreemarkerLanguageTemplateHelper;
+import org.apache.plc4x.plugins.codegenerator.protocol.freemarker.Tracer;
 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.*;
@@ -53,7 +54,7 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
 
     // TODO: check if protocol name can be enforced to only contain valid chars
     public String getSanitizedProtocolName() {
-        return getProtocolName().replaceAll("-","");
+        return getProtocolName().replaceAll("-", "");
     }
 
     public String packageName(String languageFlavorName) {
@@ -501,19 +502,25 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
     }
 
     private String toExpression(TypeReference fieldType, Term term, Argument[] parserArguments, Argument[] serializerArguments, boolean serialize, boolean suppressPointerAccess) {
+        Tracer tracer = Tracer.start("toExpression");
         if (term == null) {
             return "";
         }
         if (term instanceof Literal) {
+            tracer = tracer.dive("literal term instanceOf");
             if (term instanceof NullLiteral) {
-                return "nil";
+                tracer = tracer.dive("null literal instanceOf");
+                return tracer + "nil";
             } else if (term instanceof BooleanLiteral) {
-                return getCastExpressionForTypeReference(fieldType) + "(" + ((BooleanLiteral) term).getValue() + ")";
+                tracer = tracer.dive("null literal instanceOf");
+                return tracer + getCastExpressionForTypeReference(fieldType) + "(" + ((BooleanLiteral) term).getValue() + ")";
             } else if (term instanceof NumericLiteral) {
+                tracer = tracer.dive("numeric literal instanceOf");
                 if (getCastExpressionForTypeReference(fieldType).equals("string")) {
-                    return "(" + ((NumericLiteral) term).getNumber().toString() + ")";
+                    tracer = tracer.dive("type reference string");
+                    return tracer + "(" + ((NumericLiteral) term).getNumber().toString() + ")";
                 } else {
-                    return getCastExpressionForTypeReference(fieldType) + "(" + ((NumericLiteral) term).getNumber().toString() + ")";
+                    return tracer + getCastExpressionForTypeReference(fieldType) + "(" + ((NumericLiteral) term).getNumber().toString() + ")";
                 }
             } else if (term instanceof StringLiteral) {
                 return "\"" + ((StringLiteral) term).getValue() + "\"";
@@ -523,27 +530,33 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
                 throw new RuntimeException("Unsupported Literal type " + term.getClass().getName());
             }
         } else if (term instanceof UnaryTerm) {
+            tracer = tracer.dive("unary term instanceOf");
             UnaryTerm ut = (UnaryTerm) term;
             Term a = ut.getA();
             switch (ut.getOperation()) {
                 case "!":
-                    return "!(" + toExpression(fieldType, a, parserArguments, serializerArguments, serialize, false) + ")";
+                    tracer = tracer.dive("case !");
+                    return tracer + "!(" + toExpression(fieldType, a, parserArguments, serializerArguments, serialize, false) + ")";
                 case "-":
-                    return "-(" + getCastExpressionForTypeReference(fieldType) + "(" + toExpression(fieldType, a, parserArguments, serializerArguments, serialize, false) + "))";
+                    tracer = tracer.dive("case -");
+                    return tracer + "-(" + getCastExpressionForTypeReference(fieldType) + "(" + toExpression(fieldType, a, parserArguments, serializerArguments, serialize, false) + "))";
                 case "()":
-                    return getCastExpressionForTypeReference(fieldType) + "(" + toExpression(fieldType, a, parserArguments, serializerArguments, serialize, false) + ")";
+                    tracer = tracer.dive("case ()");
+                    return tracer + getCastExpressionForTypeReference(fieldType) + "(" + toExpression(fieldType, a, parserArguments, serializerArguments, serialize, false) + ")";
                 default:
                     throw new RuntimeException("Unsupported unary operation type " + ut.getOperation());
             }
         } else if (term instanceof BinaryTerm) {
+            tracer = tracer.dive("binary term instanceOf");
             BinaryTerm bt = (BinaryTerm) term;
             Term a = bt.getA();
             Term b = bt.getB();
             String operation = bt.getOperation();
             switch (operation) {
                 case "^":
+                    tracer = tracer.dive("^");
                     emitRequiredImport("math");
-                    return "Math.pow(" +
+                    return tracer + "Math.pow(" +
                         getCastExpressionForTypeReference(fieldType) + "(" + toExpression(fieldType, a, parserArguments, serializerArguments, serialize, false) + "), " +
                         getCastExpressionForTypeReference(fieldType) + "(" + toExpression(fieldType, b, parserArguments, serializerArguments, serialize, false) + "))";
                 // If we start casting for comparisons, equals or non equals, really messy things happen.
@@ -553,30 +566,34 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
                 case "<":
                 case ">=":
                 case "<=":
+                    tracer = tracer.dive("compare");
                     // For every access of optional elements we need pointer access ...
                     // Except for doing a nil or not-nil check :-(
                     // So in case of such a check, we need to suppress the pointer-access.
                     boolean suppressPointerAccessOverride = (operation.equals("==") || operation.equals("!=")) && ((a instanceof NullLiteral) || (b instanceof NullLiteral));
-                    return "bool((" + toExpression(null, a, parserArguments, serializerArguments, serialize, suppressPointerAccessOverride) + ") " +
+                    return tracer + "bool((" + toExpression(null, a, parserArguments, serializerArguments, serialize, suppressPointerAccessOverride) + ") " +
                         operation +
                         " (" + toExpression(null, b, parserArguments, serializerArguments, serialize, suppressPointerAccessOverride) + "))";
                 default:
+                    tracer = tracer.dive("default");
                     if (fieldType instanceof StringTypeReference) {
-                        return toExpression(fieldType, a, parserArguments, serializerArguments, serialize, false) +
+                        tracer = tracer.dive("string type reference");
+                        return tracer + toExpression(fieldType, a, parserArguments, serializerArguments, serialize, false) +
                             operation + " " +
                             toExpression(fieldType, b, parserArguments, serializerArguments, serialize, false);
                     }
-                    return getCastExpressionForTypeReference(fieldType) + "(" + toExpression(fieldType, a, parserArguments, serializerArguments, serialize, false) + ") " +
+                    return tracer + getCastExpressionForTypeReference(fieldType) + "(" + toExpression(fieldType, a, parserArguments, serializerArguments, serialize, false) + ") " +
                         operation + " " +
                         getCastExpressionForTypeReference(fieldType) + "(" + toExpression(fieldType, b, parserArguments, serializerArguments, serialize, false) + ")";
             }
         } else if (term instanceof TernaryTerm) {
+            tracer = tracer.dive("ternary term instanceOf");
             TernaryTerm tt = (TernaryTerm) term;
             if ("if".equals(tt.getOperation())) {
                 Term a = tt.getA();
                 Term b = tt.getB();
                 Term c = tt.getC();
-                return "utils.InlineIf(" + toExpression(new DefaultBooleanTypeReference(), a, parserArguments, serializerArguments, serialize, false) + ", " +
+                return tracer +"utils.InlineIf(" + toExpression(new DefaultBooleanTypeReference(), a, parserArguments, serializerArguments, serialize, false) + ", " +
                     "func() interface{} {return " + getCastExpressionForTypeReference(fieldType) + "(" + toExpression(fieldType, b, parserArguments, serializerArguments, serialize, false) + ")}, " +
                     "func() interface{} {return " + getCastExpressionForTypeReference(fieldType) + "(" + toExpression(fieldType, c, parserArguments, serializerArguments, serialize, false) + ")}).(" + getCastExpressionForTypeReference(fieldType) + ")";
             } else {
@@ -588,12 +605,15 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
     }
 
     private String toVariableExpression(TypeReference typeReference, VariableLiteral vl, Argument[] parserArguments, Argument[] serializerArguments, boolean serialize, boolean suppressPointerAccess) {
+        Tracer tracer = Tracer.start("toVariableExpression");
         if ("lengthInBytes".equals(vl.getName())) {
-            return (serialize ? getCastExpressionForTypeReference(typeReference) + "(m." : "") + "LengthInBytes()" + (serialize ? ")" : "");
+            tracer = tracer.dive("lengthInBytes");
+            return tracer + (serialize ? getCastExpressionForTypeReference(typeReference) + "(m." : "") + "LengthInBytes()" + (serialize ? ")" : "");
         } else if ("lengthInBits".equals(vl.getName())) {
-            return (serialize ? getCastExpressionForTypeReference(typeReference) + "(m." : "") + "LengthInBits()" + (serialize ? ")" : "");
+            tracer = tracer.dive("lengthInBits");
+            return tracer + (serialize ? getCastExpressionForTypeReference(typeReference) + "(m." : "") + "LengthInBits()" + (serialize ? ")" : "");
         } else if ("_value".equals(vl.getName())) {
-            if(vl.getChild() != null) {
+            if (vl.getChild() != null) {
                 return toVariableExpression(typeReference, vl.getChild(), parserArguments, serializerArguments, serialize, suppressPointerAccess);
             } else {
                 return "m";
@@ -641,7 +661,7 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
             }
             sb.append(typeLiteral.getName());
             sb.append("(").append(toVariableExpression(typeReference, (VariableLiteral) vl.getArgs().get(0), parserArguments, serializerArguments, serialize, suppressPointerAccess)).append(")");
-            return sb.toString() + ((vl.getChild() != null) ? "." + StringUtils.capitalize(toVariableExpression(typeReference, vl.getChild(), parserArguments, serializerArguments, false, suppressPointerAccess)) : "");
+            return sb + ((vl.getChild() != null) ? "." + StringUtils.capitalize(toVariableExpression(typeReference, vl.getChild(), parserArguments, serializerArguments, false, suppressPointerAccess)) : "");
         } else if ("STATIC_CALL".equals(vl.getName())) {
             StringBuilder sb = new StringBuilder();
             if (!(vl.getArgs().get(0) instanceof StringLiteral)) {
@@ -712,10 +732,12 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
             sb.append(")");
             return sb.toString();
         } else if ("COUNT".equals(vl.getName())) {
-            return (typeReference instanceof SimpleTypeReference ? getCastExpressionForTypeReference(typeReference) : "") + "(len(" +
+            tracer = tracer.dive("count");
+            return tracer + (typeReference instanceof SimpleTypeReference ? getCastExpressionForTypeReference(typeReference) : "") + "(len(" +
                 toVariableExpression(typeReference, (VariableLiteral) vl.getArgs().get(0), parserArguments, serializerArguments, serialize, suppressPointerAccess) +
                 "))";
         } else if ("ARRAY_SIZE_IN_BYTES".equals(vl.getName())) {
+            tracer = tracer.dive("array size in bytes");
             VariableLiteral va = (VariableLiteral) vl.getArgs().get(0);
             // "io" and "m" are always available in every parser.
             boolean isSerializerArg = "readBuffer".equals(va.getName()) || "writeBuffer".equals(va.getName()) || "m".equals(va.getName()) || "element".equals(va.getName());
@@ -733,7 +755,7 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
             } else {
                 sb.append(toVariableExpression(typeReference, va, parserArguments, serializerArguments, true, suppressPointerAccess));
             }
-            return getCastExpressionForTypeReference(typeReference) + "(" + ((VariableLiteral) vl.getArgs().get(0)).getName() + "ArraySizeInBytes(" + sb.toString() + "))";
+            return tracer + getCastExpressionForTypeReference(typeReference) + "(" + ((VariableLiteral) vl.getArgs().get(0)).getName() + "ArraySizeInBytes(" + sb.toString() + "))";
         } else if ("CEIL".equals(vl.getName())) {
             Term va = vl.getArgs().get(0);
             // The Ceil function expects 64 bit floating point values.
@@ -781,7 +803,7 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
                     if (matchingDiscriminatorField.isPresent()) {
                         return "Cast" + getLanguageTypeNameForTypeReference(complexTypeReference) + "(" + vl.getName() + ").Child." + StringUtils.capitalize(childProperty) + "()";
                     }
-                } else if(typeDefinition instanceof EnumTypeDefinition) {
+                } else if (typeDefinition instanceof EnumTypeDefinition) {
                     return (serialize ? "m." + StringUtils.capitalize(vl.getName()) : vl.getName()) +
                         "." + StringUtils.capitalize(vl.getChild().getName()) + "()";
                 }
@@ -1166,7 +1188,7 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
             Field field = getFieldForNameFromCurrent(propertyName);
             if (field instanceof TypedField) {
                 TypedField typedField = (TypedField) field;
-                return typedField.getType() instanceof ComplexTypeReference;
+                return typedField.getType() instanceof ComplexTypeReference && !(getTypeDefinitionForTypeReference(typedField.getType()) instanceof EnumTypeDefinition);
             }
         }
         return false;
diff --git a/code-generation/language-go/src/main/resources/templates/go/model-template.go.ftlh b/code-generation/language-go/src/main/resources/templates/go/model-template.go.ftlh
index 65689b0..7c148fc 100644
--- a/code-generation/language-go/src/main/resources/templates/go/model-template.go.ftlh
+++ b/code-generation/language-go/src/main/resources/templates/go/model-template.go.ftlh
@@ -98,6 +98,9 @@ type ${type.name} struct {
 	<#list type.propertyFields as field>
 	${field.name?cap_first} <#if field.loopType??>[]</#if><#if helper.needsPointerAccess(field)>*</#if>${helper.getLanguageTypeNameForField(field)}
 	</#list>
+    <#list type.virtualFields as field>
+        ${field.name?cap_first} <#if field.loopType??>[]</#if><#if helper.needsPointerAccess(field)>*</#if>${helper.getLanguageTypeNameForField(field)}
+    </#list>
 </#if>
 <#if helper.isDiscriminatedParentTypeDefinition()>
 	Child I${type.name}Child
@@ -150,7 +153,7 @@ type I${type.name}Parent interface {
 
 type I${type.name}Child interface {
 	Serialize(writeBuffer utils.WriteBuffer<#if helper.getSerializerArguments(type.parserArguments)?has_content>, <#list helper.getSerializerArguments(type.parserArguments) as parserArgument>${parserArgument.name} ${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}<#sep>, </#sep></#list></#if>) error
-	InitializeParent(parent *${type.name}<#if type.getPropertyFields()?has_content>, <#list type.getPropertyFields() as field>${field.name} <#if field.loopType??>[]</#if><#if helper.needsPointerAccess(field)>*</#if>${helper.getLanguageTypeNameForField(field)}<#sep>, </#sep></#list></#if>)
+	InitializeParent(parent *${type.name}<#if type.getPropertyFields()?has_content>, <#list type.getPropertyFields() as field>${field.name} <#if field.loopType??>[]</#if><#if helper.needsPointerAccess(field)>*</#if>${helper.getLanguageTypeNameForField(field)}<#sep>, </#sep></#list></#if><#if type.getPropertyFields()?has_content && type.virtualFields?has_content>, </#if><#list type.virtualFields as field>${field.name} <#if field.loopType??>[]</#if><#if helper.needsPointerAccess(field)>*</#if [...]
 	GetTypeName() string
 	I${type.name}
 }
@@ -164,7 +167,7 @@ func ${type.name}${discriminatorName?cap_first}(m I${type.name}) ${helper.getLan
 	</#list-->
 <#elseif type.parentType??>
 
-func (m *${type.name}) InitializeParent(parent *${type.parentType.name}<#if type.parentType.getAllPropertyFields()?has_content>, <#list type.parentPropertyFields as parentField>${parentField.name} <#if parentField.loopType??>[]</#if><#if helper.needsPointerAccess(parentField)>*</#if>${helper.getLanguageTypeNameForField(parentField)}<#sep>, </#sep></#list></#if>) {
+func (m *${type.name}) InitializeParent(parent *${type.parentType.name}<#if type.parentType.getAllPropertyFields()?has_content>, <#list type.parentPropertyFields as parentField>${parentField.name} <#if parentField.loopType??>[]</#if><#if helper.needsPointerAccess(parentField)>*</#if>${helper.getLanguageTypeNameForField(parentField)}<#sep>, </#sep></#list></#if><#if type.parentType.getAllPropertyFields()?has_content && type.parentType.virtualFields?has_content>, </#if><#list type.parentTy [...]
 	<#list type.parentType.getAllPropertyFields() as field>
 	m.Parent.${field.name?cap_first} = ${field.name}
 	</#list>
@@ -547,7 +550,7 @@ func (m *${type.name}) LengthInBytes() uint16 {
 	return m.LengthInBits() / 8
 }
 
-func ${type.name}Parse(readBuffer utils.ReadBuffer<#if type.parserArguments?has_content>, <#list type.parserArguments as parserArgument>${parserArgument.name} <#if helper.isComplexTypeReference(parserArgument.type)>*</#if>${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}<#sep>, </#sep></#list></#if>) (*<#if type.parentType?has_content>${type.parentType.name}<#else>${type.name}</#if>, error) {
+func ${type.name}Parse(readBuffer utils.ReadBuffer<#if type.parserArguments?has_content>, <#list type.parserArguments as parserArgument>${parserArgument.name} <#if helper.isComplexTypeReference(parserArgument.type) && !helper.isEnumTypeReference(parserArgument.type)>*</#if>${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}<#sep>, </#sep></#list></#if>) (*<#if type.parentType?has_content>${type.parentType.name}<#else>${type.name}</#if>, error) {
 	if pullErr := readBuffer.PullContext("${type.name}"); pullErr != nil {
 		return nil, pullErr
 	}
@@ -684,7 +687,7 @@ func ${type.name}Parse(readBuffer utils.ReadBuffer<#if type.parserArguments?has_
 	// Discriminator Field (${discriminatorField.name}) (Used as input to a switch field)
 	<#if helper.isEnumField(field)>
 	${helper.getVariableName(field)}_temp, _${discriminatorField.name}Err := ${helper.getLanguageTypeNameForField(discriminatorField)}Parse(readBuffer)
-	var ${helper.getVariableName(field)} *${helper.getLanguageTypeNameForField(discriminatorField)} = &${helper.getVariableName(field)}_temp
+	var ${helper.getVariableName(field)} ${helper.getLanguageTypeNameForField(discriminatorField)} = ${helper.getVariableName(field)}_temp
 	<#else>
 	${helper.getVariableName(field)}, _${discriminatorField.name}Err := ${helper.getReadBufferReadMethodCall(discriminatorField.name, simpleTypeReference)}
 	</#if>
@@ -913,7 +916,7 @@ func ${type.name}Parse(readBuffer utils.ReadBuffer<#if type.parserArguments?has_
 	switch {
 				<#list switchField.cases as case>
 					<#--TODO: refactor the line below into multiple assigns -->
-	<#if case.discriminatorValues?has_content>case <#list case.discriminatorValues as discriminatorValue><#if helper.isComplexTypeReference(helper.getDiscriminatorTypes()[helper.toParseExpression(null, switchField.discriminatorExpressions[discriminatorValue?index], type.parserArguments)])><#if helper.isEnumTypeReference(helper.getDiscriminatorTypes()[helper.toParseExpression(null, switchField.discriminatorExpressions[discriminatorValue?index], type.parserArguments)])>*</#if></#if>${helper.t [...]
+	<#if case.discriminatorValues?has_content>case <#list case.discriminatorValues as discriminatorValue><#if helper.isComplexTypeReference(helper.getDiscriminatorTypes()[helper.toParseExpression(null, switchField.discriminatorExpressions[discriminatorValue?index], type.parserArguments)])></#if>${helper.toParseExpression(null, switchField.discriminatorExpressions[discriminatorValue?index], type.parserArguments)} == <#if helper.discriminatorValueNeedsStringEqualityCheck(switchField.discrimin [...]
 		_parent, typeSwitchError = ${case.name}Parse(readBuffer<#if case.parserArguments?has_content>, <#list case.parserArguments as parserArgument><#if helper.isOptionalField(helper.getFieldForNameFromCurrentOrParent(parserArgument.name))>*</#if>${parserArgument.name}<#sep>, </#sep></#list></#if>)
 				</#list>
 	default:
@@ -938,11 +941,8 @@ func ${type.name}Parse(readBuffer utils.ReadBuffer<#if type.parserArguments?has_
 			<#case "virtual">
 				<#assign virtualField = field>
 
-	// Virtual field (Just declare a local variable so we can access it in the parser)
-	${virtualField.name}, _${virtualField.name}Err := ${helper.toParseExpression(virtualField, virtualField.valueExpression, type.parserArguments)}
-	if _${virtualField.name}Err != nil {
-		return nil, errors.Wrap(_${virtualField.name}Err, "Error parsing '${virtualField.name}' field")<@emitImport import="github.com/pkg/errors" />
-	}
+	// Virtual field
+	${virtualField.name} := ${helper.toParseExpression(virtualField, virtualField.valueExpression, type.parserArguments)}
 				<#break>
 		</#switch>
 	</#list>
@@ -953,7 +953,7 @@ func ${type.name}Parse(readBuffer utils.ReadBuffer<#if type.parserArguments?has_
 
 	<#if helper.isDiscriminatedParentTypeDefinition()>
 	// Finish initializing
-	_parent.Child.InitializeParent(_parent<#if type.propertyFields?has_content>, <#list type.propertyFields as field>${field.name}<#sep>, </#sep></#list></#if>)
+	_parent.Child.InitializeParent(_parent<#if type.propertyFields?has_content>, <#list type.propertyFields as field>${field.name}<#sep>, </#sep></#list></#if><#if type.propertyFields?has_content && type.virtualFields?has_content>, </#if><#list type.virtualFields as field>${field.name}<#sep>, </#sep></#list>)
 	return _parent, nil
 	<#elseif type.parentType?has_content>
 	// Create a partially initialized instance
@@ -967,7 +967,7 @@ func ${type.name}Parse(readBuffer utils.ReadBuffer<#if type.parserArguments?has_
 	return _child.Parent, nil
 	<#else>
 	// Create the instance
-	return New${type.name}(<#list type.propertyFields as field>${field.name}<#sep>, </#sep></#list>), nil
+	return New${type.name}(<#list type.propertyFields as field>${field.name}<#sep>, </#sep></#list><#if type.propertyFields?has_content && type.virtualFields?has_content>, </#if><#list type.virtualFields as field>${field.name}<#sep>, </#sep></#list>), nil
 	</#if>
 }
 
diff --git a/code-generation/language-go/src/main/resources/templates/go/parser-factory-template.go.ftlh b/code-generation/language-go/src/main/resources/templates/go/parser-factory-template.go.ftlh
index 204772c..76a4df7 100644
--- a/code-generation/language-go/src/main/resources/templates/go/parser-factory-template.go.ftlh
+++ b/code-generation/language-go/src/main/resources/templates/go/parser-factory-template.go.ftlh
@@ -90,7 +90,7 @@ func (m ${helper.getSanitizedProtocolName()?cap_first}ParserHelper) Parse(typeNa
 			</#if>
 		</#list>
 	</#if>
-		return model.${typeDefinition.name}Parse(io<#if typeDefinition.parserArguments?has_content>, <#list typeDefinition.parserArguments as parserArgument><#if helper.isComplexTypeReference(parserArgument.type)>&</#if>${parserArgument.name}<#sep>, </#list></#if>)
+		return model.${typeDefinition.name}Parse(io<#if typeDefinition.parserArguments?has_content>, <#list typeDefinition.parserArguments as parserArgument><#if helper.isComplexTypeReference(parserArgument.type) && !helper.isEnumTypeReference(parserArgument.type)>&</#if>${parserArgument.name}<#sep>, </#list></#if>)
 </#list>
 	}
 	return nil, errors.Errorf("Unsupported type %s", typeName)
diff --git a/code-generation/language-go/src/main/resources/templates/go/xml-parser-factory-template.go.ftlh b/code-generation/language-go/src/main/resources/templates/go/xml-parser-factory-template.go.ftlh
index fe0f922..480a8c5 100644
--- a/code-generation/language-go/src/main/resources/templates/go/xml-parser-factory-template.go.ftlh
+++ b/code-generation/language-go/src/main/resources/templates/go/xml-parser-factory-template.go.ftlh
@@ -132,7 +132,7 @@ func (m ${helper.getSanitizedProtocolName()?cap_first}XmlParserHelper) Parse(typ
                     </#switch>
                 </#if>
             </#list>
-            <#assign parserArgumentList><#list typeDefinition.parserArguments as parserArgument><#if helper.isEnumTypeReference(parserArgument.type) || helper.isComplexTypeReference(parserArgument.type)>&</#if>${parserArgument.name}<#sep>, </#sep> </#list> </#assign>
+            <#assign parserArgumentList><#list typeDefinition.parserArguments as parserArgument><#if helper.isComplexTypeReference(parserArgument.type) && !helper.isEnumTypeReference(parserArgument.type)>&</#if>${parserArgument.name}<#sep>, </#sep> </#list> </#assign>
             return model.${typeDefinition.name}Parse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)), ${parserArgumentList})
         <#else>
 			return model.${typeDefinition.name}Parse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
diff --git a/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java b/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
index 8af94ee..39973ee 100644
--- a/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
+++ b/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
@@ -19,6 +19,7 @@
 package org.apache.plc4x.language.java;
 
 import java.util.Optional;
+
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.math.NumberUtils;
 import org.apache.commons.text.WordUtils;
@@ -37,7 +38,7 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
     private final Map<String, String> options;
 
     public JavaLanguageTemplateHelper(TypeDefinition thisType, String protocolName, String flavorName, Map<String, TypeDefinition> types,
-        Map<String, String> options) {
+                                      Map<String, String> options) {
         super(thisType, protocolName, flavorName, types);
         this.options = options;
     }
@@ -532,6 +533,16 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
         return types.values();
     }*/
 
+    public String toAccessExpression(TypedField field, Term term, Argument[] parserArguments) {
+        return toExpression(field, term, term1 -> {
+            VariableLiteral vl = (VariableLiteral) term1;
+            if (isVariableLiteralVirtualField(vl) || isVariableLiteralDiscriminatorField(vl)) { // If we are accessing virtual|discriminator fields, we need to call the getter.
+                return "get" + StringUtils.capitalize(vl.getName()) + "()";
+            }
+            return toVariableParseExpression(field, term1, parserArguments);
+        });
+    }
+
     public String toParseExpression(TypedField field, Term term, Argument[] parserArguments) {
         return toExpression(field, term, term1 -> toVariableParseExpression(field, term1, parserArguments));
     }
@@ -615,7 +626,7 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
             }
             sb.append("(").append(toVariableParseExpression(field, vl.getArgs().get(0), parserArguments))
                 .append(", ").append(((VariableLiteral) vl.getArgs().get(1)).getName()).append(".class)");
-            return sb.toString() + ((vl.getChild() != null) ? "." + toVariableExpressionRest(vl.getChild()) : "");
+            return sb + ((vl.getChild() != null) ? "." + toVariableExpressionRest(vl.getChild()) : "");
         } else if ("STATIC_CALL".equals(vl.getName())) {
             StringBuilder sb = new StringBuilder();
             if (!(vl.getArgs().get(0) instanceof StringLiteral)) {
@@ -645,10 +656,8 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
                         }
                     }
                     if (isParserArg) {
-                        sb.append(va.getName() + ((va.getChild() != null) ? "." + toVariableExpressionRest(va.getChild()) : ""));
-                    }
-                    // We have to manually evaluate the type information at code-generation time.
-                    else if (isTypeArg) {
+                        sb.append(va.getName()).append((va.getChild() != null) ? "." + toVariableExpressionRest(va.getChild()) : "");
+                    } else if (isTypeArg) {// We have to manually evaluate the type information at code-generation time.
                         String part = va.getChild().getName();
                         switch (part) {
                             case "name":
@@ -673,13 +682,9 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
             }
             sb.append(")");
             return sb.toString();
-        }
-        // If we are accessing implicit fields, we need to rely on a local variable instead.
-        else if (isVariableLiteralImplicitField(vl)) {
+        } else if (isVariableLiteralImplicitField(vl)) { // If we are accessing implicit fields, we need to rely on a local variable instead.
             return vl.getName();
-        }
-        // All uppercase names are not fields, but utility methods.
-        else if (vl.getName().equals(vl.getName().toUpperCase())) {
+        } else if (vl.getName().equals(vl.getName().toUpperCase())) { // All uppercase names are not fields, but utility methods.
             StringBuilder sb = new StringBuilder(vl.getName());
             if (vl.getArgs() != null) {
                 sb.append("(");
@@ -696,7 +701,7 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
             if (vl.getIndex() != VariableLiteral.NO_INDEX) {
                 sb.append("[").append(vl.getIndex()).append("]");
             }
-            return sb.toString() + ((vl.getChild() != null) ? "." + toVariableExpressionRest(vl.getChild()) : "");
+            return sb + ((vl.getChild() != null) ? "." + toVariableExpressionRest(vl.getChild()) : "");
         }
         return vl.getName() + ((vl.getChild() != null) ? "." + toVariableExpressionRest(vl.getChild()) : "");
     }
diff --git a/code-generation/language-java/src/main/resources/templates/java/pojo-template.java.ftlh b/code-generation/language-java/src/main/resources/templates/java/pojo-template.java.ftlh
index e8b5677..582c94a 100644
--- a/code-generation/language-java/src/main/resources/templates/java/pojo-template.java.ftlh
+++ b/code-generation/language-java/src/main/resources/templates/java/pojo-template.java.ftlh
@@ -159,9 +159,9 @@ public<#if helper.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${
     <#if !helper.isDiscriminatorField(field.name)>
     public ${helper.getLanguageTypeNameForField(field)}<#if field.loopType??>[]</#if> get${field.name?cap_first}() {
         <#if helper.getLanguageTypeNameForField(field) = 'String'>
-        return ${helper.getLanguageTypeNameForField(field)}.valueOf(${helper.toParseExpression(field, field.valueExpression, type.parserArguments)});
+        return ${helper.getLanguageTypeNameForField(field)}.valueOf(${helper.toAccessExpression(field, field.valueExpression, type.parserArguments)});
         <#else>
-        return (${helper.getLanguageTypeNameForField(field)}) (${helper.toParseExpression(field, field.valueExpression, type.parserArguments)});
+        return (${helper.getLanguageTypeNameForField(field)}) (${helper.toAccessExpression(field, field.valueExpression, type.parserArguments)});
         </#if>
     }
     </#if>
diff --git a/plc4go/internal/plc4go/ads/readwrite/ParserHelper.go b/plc4go/internal/plc4go/ads/readwrite/ParserHelper.go
index 4365002..c11a5e1 100644
--- a/plc4go/internal/plc4go/ads/readwrite/ParserHelper.go
+++ b/plc4go/internal/plc4go/ads/readwrite/ParserHelper.go
@@ -54,7 +54,7 @@ func (m AdsParserHelper) Parse(typeName string, arguments []string, io utils.Rea
 		if err != nil {
 			return nil, errors.Wrap(err, "Error parsing")
 		}
-		return model.AdsDataParse(io, &commandId, response)
+		return model.AdsDataParse(io, commandId, response)
 	case "AmsNetId":
 		return model.AmsNetIdParse(io)
 	case "AdsStampHeader":
diff --git a/plc4go/internal/plc4go/ads/readwrite/XmlParserHelper.go b/plc4go/internal/plc4go/ads/readwrite/XmlParserHelper.go
index 1f8f1ca..616c149 100644
--- a/plc4go/internal/plc4go/ads/readwrite/XmlParserHelper.go
+++ b/plc4go/internal/plc4go/ads/readwrite/XmlParserHelper.go
@@ -62,7 +62,7 @@ func (m AdsXmlParserHelper) Parse(typeName string, xmlString string, parserArgum
 	case "AdsData":
 		commandId := model.CommandIdByName(parserArguments[0])
 		response := parserArguments[1] == "true"
-		return model.AdsDataParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)), &commandId, response)
+		return model.AdsDataParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)), commandId, response)
 	case "AmsNetId":
 		return model.AmsNetIdParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
 	case "AdsStampHeader":
diff --git a/plc4go/internal/plc4go/ads/readwrite/model/AdsData.go b/plc4go/internal/plc4go/ads/readwrite/model/AdsData.go
index d6998f7..a6b631a 100644
--- a/plc4go/internal/plc4go/ads/readwrite/model/AdsData.go
+++ b/plc4go/internal/plc4go/ads/readwrite/model/AdsData.go
@@ -91,7 +91,7 @@ func (m *AdsData) LengthInBytes() uint16 {
 	return m.LengthInBits() / 8
 }
 
-func AdsDataParse(readBuffer utils.ReadBuffer, commandId *CommandId, response bool) (*AdsData, error) {
+func AdsDataParse(readBuffer utils.ReadBuffer, commandId CommandId, response bool) (*AdsData, error) {
 	if pullErr := readBuffer.PullContext("AdsData"); pullErr != nil {
 		return nil, pullErr
 	}
@@ -100,45 +100,45 @@ func AdsDataParse(readBuffer utils.ReadBuffer, commandId *CommandId, response bo
 	var _parent *AdsData
 	var typeSwitchError error
 	switch {
-	case *commandId == CommandId_INVALID && response == false: // AdsInvalidRequest
+	case commandId == CommandId_INVALID && response == false: // AdsInvalidRequest
 		_parent, typeSwitchError = AdsInvalidRequestParse(readBuffer)
-	case *commandId == CommandId_INVALID && response == true: // AdsInvalidResponse
+	case commandId == CommandId_INVALID && response == true: // AdsInvalidResponse
 		_parent, typeSwitchError = AdsInvalidResponseParse(readBuffer)
-	case *commandId == CommandId_ADS_READ_DEVICE_INFO && response == false: // AdsReadDeviceInfoRequest
+	case commandId == CommandId_ADS_READ_DEVICE_INFO && response == false: // AdsReadDeviceInfoRequest
 		_parent, typeSwitchError = AdsReadDeviceInfoRequestParse(readBuffer)
-	case *commandId == CommandId_ADS_READ_DEVICE_INFO && response == true: // AdsReadDeviceInfoResponse
+	case commandId == CommandId_ADS_READ_DEVICE_INFO && response == true: // AdsReadDeviceInfoResponse
 		_parent, typeSwitchError = AdsReadDeviceInfoResponseParse(readBuffer)
-	case *commandId == CommandId_ADS_READ && response == false: // AdsReadRequest
+	case commandId == CommandId_ADS_READ && response == false: // AdsReadRequest
 		_parent, typeSwitchError = AdsReadRequestParse(readBuffer)
-	case *commandId == CommandId_ADS_READ && response == true: // AdsReadResponse
+	case commandId == CommandId_ADS_READ && response == true: // AdsReadResponse
 		_parent, typeSwitchError = AdsReadResponseParse(readBuffer)
-	case *commandId == CommandId_ADS_WRITE && response == false: // AdsWriteRequest
+	case commandId == CommandId_ADS_WRITE && response == false: // AdsWriteRequest
 		_parent, typeSwitchError = AdsWriteRequestParse(readBuffer)
-	case *commandId == CommandId_ADS_WRITE && response == true: // AdsWriteResponse
+	case commandId == CommandId_ADS_WRITE && response == true: // AdsWriteResponse
 		_parent, typeSwitchError = AdsWriteResponseParse(readBuffer)
-	case *commandId == CommandId_ADS_READ_STATE && response == false: // AdsReadStateRequest
+	case commandId == CommandId_ADS_READ_STATE && response == false: // AdsReadStateRequest
 		_parent, typeSwitchError = AdsReadStateRequestParse(readBuffer)
-	case *commandId == CommandId_ADS_READ_STATE && response == true: // AdsReadStateResponse
+	case commandId == CommandId_ADS_READ_STATE && response == true: // AdsReadStateResponse
 		_parent, typeSwitchError = AdsReadStateResponseParse(readBuffer)
-	case *commandId == CommandId_ADS_WRITE_CONTROL && response == false: // AdsWriteControlRequest
+	case commandId == CommandId_ADS_WRITE_CONTROL && response == false: // AdsWriteControlRequest
 		_parent, typeSwitchError = AdsWriteControlRequestParse(readBuffer)
-	case *commandId == CommandId_ADS_WRITE_CONTROL && response == true: // AdsWriteControlResponse
+	case commandId == CommandId_ADS_WRITE_CONTROL && response == true: // AdsWriteControlResponse
 		_parent, typeSwitchError = AdsWriteControlResponseParse(readBuffer)
-	case *commandId == CommandId_ADS_ADD_DEVICE_NOTIFICATION && response == false: // AdsAddDeviceNotificationRequest
+	case commandId == CommandId_ADS_ADD_DEVICE_NOTIFICATION && response == false: // AdsAddDeviceNotificationRequest
 		_parent, typeSwitchError = AdsAddDeviceNotificationRequestParse(readBuffer)
-	case *commandId == CommandId_ADS_ADD_DEVICE_NOTIFICATION && response == true: // AdsAddDeviceNotificationResponse
+	case commandId == CommandId_ADS_ADD_DEVICE_NOTIFICATION && response == true: // AdsAddDeviceNotificationResponse
 		_parent, typeSwitchError = AdsAddDeviceNotificationResponseParse(readBuffer)
-	case *commandId == CommandId_ADS_DELETE_DEVICE_NOTIFICATION && response == false: // AdsDeleteDeviceNotificationRequest
+	case commandId == CommandId_ADS_DELETE_DEVICE_NOTIFICATION && response == false: // AdsDeleteDeviceNotificationRequest
 		_parent, typeSwitchError = AdsDeleteDeviceNotificationRequestParse(readBuffer)
-	case *commandId == CommandId_ADS_DELETE_DEVICE_NOTIFICATION && response == true: // AdsDeleteDeviceNotificationResponse
+	case commandId == CommandId_ADS_DELETE_DEVICE_NOTIFICATION && response == true: // AdsDeleteDeviceNotificationResponse
 		_parent, typeSwitchError = AdsDeleteDeviceNotificationResponseParse(readBuffer)
-	case *commandId == CommandId_ADS_DEVICE_NOTIFICATION && response == false: // AdsDeviceNotificationRequest
+	case commandId == CommandId_ADS_DEVICE_NOTIFICATION && response == false: // AdsDeviceNotificationRequest
 		_parent, typeSwitchError = AdsDeviceNotificationRequestParse(readBuffer)
-	case *commandId == CommandId_ADS_DEVICE_NOTIFICATION && response == true: // AdsDeviceNotificationResponse
+	case commandId == CommandId_ADS_DEVICE_NOTIFICATION && response == true: // AdsDeviceNotificationResponse
 		_parent, typeSwitchError = AdsDeviceNotificationResponseParse(readBuffer)
-	case *commandId == CommandId_ADS_READ_WRITE && response == false: // AdsReadWriteRequest
+	case commandId == CommandId_ADS_READ_WRITE && response == false: // AdsReadWriteRequest
 		_parent, typeSwitchError = AdsReadWriteRequestParse(readBuffer)
-	case *commandId == CommandId_ADS_READ_WRITE && response == true: // AdsReadWriteResponse
+	case commandId == CommandId_ADS_READ_WRITE && response == true: // AdsReadWriteResponse
 		_parent, typeSwitchError = AdsReadWriteResponseParse(readBuffer)
 	default:
 		// TODO: return actual type
diff --git a/plc4go/internal/plc4go/ads/readwrite/model/AdsReadWriteRequest.go b/plc4go/internal/plc4go/ads/readwrite/model/AdsReadWriteRequest.go
index fdb757c..df5b4ea 100644
--- a/plc4go/internal/plc4go/ads/readwrite/model/AdsReadWriteRequest.go
+++ b/plc4go/internal/plc4go/ads/readwrite/model/AdsReadWriteRequest.go
@@ -167,8 +167,8 @@ func AdsReadWriteRequestParse(readBuffer utils.ReadBuffer) (*AdsData, error) {
 		return nil, pullErr
 	}
 	// Count array
-	items := make([]*AdsMultiRequestItem, utils.InlineIf(bool(bool(bool(bool(bool((indexGroup) == (61568)))) || bool(bool(bool((indexGroup) == (61569))))) || bool(bool(bool((indexGroup) == (61570))))), func() uint16 { return uint16(indexOffset) }, func() uint16 { return uint16(uint16(0)) }))
-	for curItem := uint16(0); curItem < uint16(utils.InlineIf(bool(bool(bool(bool(bool((indexGroup) == (61568)))) || bool(bool(bool((indexGroup) == (61569))))) || bool(bool(bool((indexGroup) == (61570))))), func() uint16 { return uint16(indexOffset) }, func() uint16 { return uint16(uint16(0)) })); curItem++ {
+	items := make([]*AdsMultiRequestItem, utils.InlineIf(bool(bool(bool(bool(bool((indexGroup) == (61568)))) || bool(bool(bool((indexGroup) == (61569))))) || bool(bool(bool((indexGroup) == (61570))))), func() interface{} { return uint16(indexOffset) }, func() interface{} { return uint16(uint16(0)) }).(uint16))
+	for curItem := uint16(0); curItem < uint16(utils.InlineIf(bool(bool(bool(bool(bool((indexGroup) == (61568)))) || bool(bool(bool((indexGroup) == (61569))))) || bool(bool(bool((indexGroup) == (61570))))), func() interface{} { return uint16(indexOffset) }, func() interface{} { return uint16(uint16(0)) }).(uint16)); curItem++ {
 		_item, _err := AdsMultiRequestItemParse(readBuffer, indexGroup)
 		if _err != nil {
 			return nil, errors.Wrap(_err, "Error parsing 'items' field")
@@ -241,7 +241,7 @@ func (m *AdsReadWriteRequest) Serialize(writeBuffer utils.WriteBuffer) error {
 		}
 
 		// Implicit Field (writeLength) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
-		writeLength := uint32(uint32(uint32(uint32(uint32(len(m.Items)))*uint32(uint32(utils.InlineIf(bool(bool((m.IndexGroup) == (61570))), func() uint16 { return uint16(uint32(16)) }, func() uint16 { return uint16(uint32(12)) }))))) + uint32(uint32(len(m.Data))))
+		writeLength := uint32(uint32(uint32(uint32(uint32(len(m.Items)))*uint32(uint32(utils.InlineIf(bool(bool((m.IndexGroup) == (61570))), func() interface{} { return uint32(uint32(16)) }, func() interface{} { return uint32(uint32(12)) }).(uint32))))) + uint32(uint32(len(m.Data))))
 		_writeLengthErr := writeBuffer.WriteUint32("writeLength", 32, (writeLength))
 		if _writeLengthErr != nil {
 			return errors.Wrap(_writeLengthErr, "Error serializing 'writeLength' field")
diff --git a/plc4go/internal/plc4go/ads/readwrite/model/AmsPacket.go b/plc4go/internal/plc4go/ads/readwrite/model/AmsPacket.go
index 0ba701c..5f26363 100644
--- a/plc4go/internal/plc4go/ads/readwrite/model/AmsPacket.go
+++ b/plc4go/internal/plc4go/ads/readwrite/model/AmsPacket.go
@@ -199,7 +199,7 @@ func AmsPacketParse(readBuffer utils.ReadBuffer) (*AmsPacket, error) {
 	if pullErr := readBuffer.PullContext("data"); pullErr != nil {
 		return nil, pullErr
 	}
-	data, _dataErr := AdsDataParse(readBuffer, &commandId, state.Response)
+	data, _dataErr := AdsDataParse(readBuffer, commandId, state.Response)
 	if _dataErr != nil {
 		return nil, errors.Wrap(_dataErr, "Error parsing 'data' field")
 	}
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/ParserHelper.go b/plc4go/internal/plc4go/knxnetip/readwrite/ParserHelper.go
index 3f283e5..3ff86ed 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/ParserHelper.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/ParserHelper.go
@@ -78,7 +78,7 @@ func (m KnxnetipParserHelper) Parse(typeName string, arguments []string, io util
 		return model.CEMIAdditionalInformationParse(io)
 	case "ComObjectTable":
 		var firmwareType model.FirmwareType
-		return model.ComObjectTableParse(io, &firmwareType)
+		return model.ComObjectTableParse(io, firmwareType)
 	case "KnxAddress":
 		return model.KnxAddressParse(io)
 	case "ConnectionResponseDataBlock":
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/XmlParserHelper.go b/plc4go/internal/plc4go/knxnetip/readwrite/XmlParserHelper.go
index 1357380..06e76e4 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/XmlParserHelper.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/XmlParserHelper.go
@@ -90,7 +90,7 @@ func (m KnxnetipXmlParserHelper) Parse(typeName string, xmlString string, parser
 		return model.CEMIAdditionalInformationParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
 	case "ComObjectTable":
 		firmwareType := model.FirmwareTypeByName(parserArguments[0])
-		return model.ComObjectTableParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)), &firmwareType)
+		return model.ComObjectTableParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)), firmwareType)
 	case "KnxAddress":
 		return model.KnxAddressParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
 	case "ConnectionResponseDataBlock":
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataDeviceDescriptorResponse.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataDeviceDescriptorResponse.go
index ceb7662..314a49c 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataDeviceDescriptorResponse.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataDeviceDescriptorResponse.go
@@ -121,8 +121,8 @@ func ApduDataDeviceDescriptorResponseParse(readBuffer utils.ReadBuffer, dataLeng
 		return nil, pullErr
 	}
 	// Count array
-	data := make([]int8, utils.InlineIf(bool(bool((dataLength) < (1))), func() uint16 { return uint16(uint16(0)) }, func() uint16 { return uint16(uint16(dataLength) - uint16(uint16(1))) }))
-	for curItem := uint16(0); curItem < uint16(utils.InlineIf(bool(bool((dataLength) < (1))), func() uint16 { return uint16(uint16(0)) }, func() uint16 { return uint16(uint16(dataLength) - uint16(uint16(1))) })); curItem++ {
+	data := make([]int8, utils.InlineIf(bool(bool((dataLength) < (1))), func() interface{} { return uint16(uint16(0)) }, func() interface{} { return uint16(uint16(dataLength) - uint16(uint16(1))) }).(uint16))
+	for curItem := uint16(0); curItem < uint16(utils.InlineIf(bool(bool((dataLength) < (1))), func() interface{} { return uint16(uint16(0)) }, func() interface{} { return uint16(uint16(dataLength) - uint16(uint16(1))) }).(uint16)); curItem++ {
 		_item, _err := readBuffer.ReadInt8("", 8)
 		if _err != nil {
 			return nil, errors.Wrap(_err, "Error parsing 'data' field")
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataGroupValueResponse.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataGroupValueResponse.go
index f9b31c5..8564cf3 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataGroupValueResponse.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataGroupValueResponse.go
@@ -121,8 +121,8 @@ func ApduDataGroupValueResponseParse(readBuffer utils.ReadBuffer, dataLength uin
 		return nil, pullErr
 	}
 	// Count array
-	data := make([]int8, utils.InlineIf(bool(bool((dataLength) < (1))), func() uint16 { return uint16(uint16(0)) }, func() uint16 { return uint16(uint16(dataLength) - uint16(uint16(1))) }))
-	for curItem := uint16(0); curItem < uint16(utils.InlineIf(bool(bool((dataLength) < (1))), func() uint16 { return uint16(uint16(0)) }, func() uint16 { return uint16(uint16(dataLength) - uint16(uint16(1))) })); curItem++ {
+	data := make([]int8, utils.InlineIf(bool(bool((dataLength) < (1))), func() interface{} { return uint16(uint16(0)) }, func() interface{} { return uint16(uint16(dataLength) - uint16(uint16(1))) }).(uint16))
+	for curItem := uint16(0); curItem < uint16(utils.InlineIf(bool(bool((dataLength) < (1))), func() interface{} { return uint16(uint16(0)) }, func() interface{} { return uint16(uint16(dataLength) - uint16(uint16(1))) }).(uint16)); curItem++ {
 		_item, _err := readBuffer.ReadInt8("", 8)
 		if _err != nil {
 			return nil, errors.Wrap(_err, "Error parsing 'data' field")
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataGroupValueWrite.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataGroupValueWrite.go
index e84273b..da6b224 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataGroupValueWrite.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/ApduDataGroupValueWrite.go
@@ -121,8 +121,8 @@ func ApduDataGroupValueWriteParse(readBuffer utils.ReadBuffer, dataLength uint8)
 		return nil, pullErr
 	}
 	// Count array
-	data := make([]int8, utils.InlineIf(bool(bool((dataLength) < (1))), func() uint16 { return uint16(uint16(0)) }, func() uint16 { return uint16(uint16(dataLength) - uint16(uint16(1))) }))
-	for curItem := uint16(0); curItem < uint16(utils.InlineIf(bool(bool((dataLength) < (1))), func() uint16 { return uint16(uint16(0)) }, func() uint16 { return uint16(uint16(dataLength) - uint16(uint16(1))) })); curItem++ {
+	data := make([]int8, utils.InlineIf(bool(bool((dataLength) < (1))), func() interface{} { return uint16(uint16(0)) }, func() interface{} { return uint16(uint16(dataLength) - uint16(uint16(1))) }).(uint16))
+	for curItem := uint16(0); curItem < uint16(utils.InlineIf(bool(bool((dataLength) < (1))), func() interface{} { return uint16(uint16(0)) }, func() interface{} { return uint16(uint16(dataLength) - uint16(uint16(1))) }).(uint16)); curItem++ {
 		_item, _err := readBuffer.ReadInt8("", 8)
 		if _err != nil {
 			return nil, errors.Wrap(_err, "Error parsing 'data' field")
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/ComObjectTable.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/ComObjectTable.go
index 5600a16..689a7c9 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/ComObjectTable.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/ComObjectTable.go
@@ -90,7 +90,7 @@ func (m *ComObjectTable) LengthInBytes() uint16 {
 	return m.LengthInBits() / 8
 }
 
-func ComObjectTableParse(readBuffer utils.ReadBuffer, firmwareType *FirmwareType) (*ComObjectTable, error) {
+func ComObjectTableParse(readBuffer utils.ReadBuffer, firmwareType FirmwareType) (*ComObjectTable, error) {
 	if pullErr := readBuffer.PullContext("ComObjectTable"); pullErr != nil {
 		return nil, pullErr
 	}
@@ -99,11 +99,11 @@ func ComObjectTableParse(readBuffer utils.ReadBuffer, firmwareType *FirmwareType
 	var _parent *ComObjectTable
 	var typeSwitchError error
 	switch {
-	case *firmwareType == FirmwareType_SYSTEM_1: // ComObjectTableRealisationType1
+	case firmwareType == FirmwareType_SYSTEM_1: // ComObjectTableRealisationType1
 		_parent, typeSwitchError = ComObjectTableRealisationType1Parse(readBuffer)
-	case *firmwareType == FirmwareType_SYSTEM_2: // ComObjectTableRealisationType2
+	case firmwareType == FirmwareType_SYSTEM_2: // ComObjectTableRealisationType2
 		_parent, typeSwitchError = ComObjectTableRealisationType2Parse(readBuffer)
-	case *firmwareType == FirmwareType_SYSTEM_300: // ComObjectTableRealisationType6
+	case firmwareType == FirmwareType_SYSTEM_300: // ComObjectTableRealisationType6
 		_parent, typeSwitchError = ComObjectTableRealisationType6Parse(readBuffer)
 	default:
 		// TODO: return actual type
diff --git a/plc4go/internal/plc4go/s7/readwrite/model/COTPPacket.go b/plc4go/internal/plc4go/s7/readwrite/model/COTPPacket.go
index 64472b9..7776c6c 100644
--- a/plc4go/internal/plc4go/s7/readwrite/model/COTPPacket.go
+++ b/plc4go/internal/plc4go/s7/readwrite/model/COTPPacket.go
@@ -204,7 +204,7 @@ func (m *COTPPacket) SerializeParent(writeBuffer utils.WriteBuffer, child ICOTPP
 	}
 
 	// Implicit Field (headerLength) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
-	headerLength := uint8(uint8(uint8(m.LengthInBytes())) - uint8(uint8(uint8(uint8(utils.InlineIf(bool(bool((m.Payload) != (nil))), func() uint16 { return uint16(m.Payload.LengthInBytes()) }, func() uint16 { return uint16(uint8(0)) })))+uint8(uint8(1)))))
+	headerLength := uint8(uint8(uint8(m.LengthInBytes())) - uint8(uint8(uint8(uint8(utils.InlineIf(bool(bool((m.Payload) != (nil))), func() interface{} { return uint8(m.Payload.LengthInBytes()) }, func() interface{} { return uint8(uint8(0)) }).(uint8)))+uint8(uint8(1)))))
 	_headerLengthErr := writeBuffer.WriteUint8("headerLength", 8, (headerLength))
 	if _headerLengthErr != nil {
 		return errors.Wrap(_headerLengthErr, "Error serializing 'headerLength' field")
diff --git a/plc4go/internal/plc4go/s7/readwrite/model/S7Message.go b/plc4go/internal/plc4go/s7/readwrite/model/S7Message.go
index 7294a84..0512549 100644
--- a/plc4go/internal/plc4go/s7/readwrite/model/S7Message.go
+++ b/plc4go/internal/plc4go/s7/readwrite/model/S7Message.go
@@ -267,14 +267,14 @@ func (m *S7Message) SerializeParent(writeBuffer utils.WriteBuffer, child IS7Mess
 	}
 
 	// Implicit Field (parameterLength) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
-	parameterLength := uint16(utils.InlineIf(bool((m.Parameter) != (nil)), func() uint16 { return uint16(m.Parameter.LengthInBytes()) }, func() uint16 { return uint16(uint16(0)) }))
+	parameterLength := uint16(utils.InlineIf(bool((m.Parameter) != (nil)), func() interface{} { return uint16(m.Parameter.LengthInBytes()) }, func() interface{} { return uint16(uint16(0)) }).(uint16))
 	_parameterLengthErr := writeBuffer.WriteUint16("parameterLength", 16, (parameterLength))
 	if _parameterLengthErr != nil {
 		return errors.Wrap(_parameterLengthErr, "Error serializing 'parameterLength' field")
 	}
 
 	// Implicit Field (payloadLength) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
-	payloadLength := uint16(utils.InlineIf(bool((m.Payload) != (nil)), func() uint16 { return uint16(m.Payload.LengthInBytes()) }, func() uint16 { return uint16(uint16(0)) }))
+	payloadLength := uint16(utils.InlineIf(bool((m.Payload) != (nil)), func() interface{} { return uint16(m.Payload.LengthInBytes()) }, func() interface{} { return uint16(uint16(0)) }).(uint16))
 	_payloadLengthErr := writeBuffer.WriteUint16("payloadLength", 16, (payloadLength))
 	if _payloadLengthErr != nil {
 		return errors.Wrap(_payloadLengthErr, "Error serializing 'payloadLength' field")
diff --git a/plc4go/internal/plc4go/s7/readwrite/model/S7VarPayloadDataItem.go b/plc4go/internal/plc4go/s7/readwrite/model/S7VarPayloadDataItem.go
index 5e259e6..7bf9956 100644
--- a/plc4go/internal/plc4go/s7/readwrite/model/S7VarPayloadDataItem.go
+++ b/plc4go/internal/plc4go/s7/readwrite/model/S7VarPayloadDataItem.go
@@ -84,7 +84,7 @@ func (m *S7VarPayloadDataItem) LengthInBitsConditional(lastItem bool) uint16 {
 	}
 
 	// Padding Field (padding)
-	_timesPadding := uint8(utils.InlineIf(lastItem, func() uint16 { return uint16(uint8(0)) }, func() uint16 { return uint16(uint8(uint8(len(m.Data))) % uint8(uint8(2))) }))
+	_timesPadding := uint8(utils.InlineIf(lastItem, func() interface{} { return uint8(uint8(0)) }, func() interface{} { return uint8(uint8(uint8(len(m.Data))) % uint8(uint8(2))) }).(uint8))
 	for ; _timesPadding > 0; _timesPadding-- {
 		lengthInBits += 8
 	}
@@ -132,7 +132,7 @@ func S7VarPayloadDataItemParse(readBuffer utils.ReadBuffer, lastItem bool) (*S7V
 		return nil, errors.Wrap(_dataLengthErr, "Error parsing 'dataLength' field")
 	}
 	// Byte Array field (data)
-	numberOfBytes := int(utils.InlineIf(transportSize.SizeInBits(), func() uint16 { return uint16(math.Ceil(float64(dataLength) / float64(float64(8.0)))) }, func() uint16 { return uint16(dataLength) }))
+	numberOfBytes := int(utils.InlineIf(transportSize.SizeInBits(), func() interface{} { return uint16(math.Ceil(float64(dataLength) / float64(float64(8.0)))) }, func() interface{} { return uint16(dataLength) }).(uint16))
 	data, _readArrayErr := readBuffer.ReadByteArray("data", numberOfBytes)
 	if _readArrayErr != nil {
 		return nil, errors.Wrap(_readArrayErr, "Error parsing 'data' field")
@@ -143,7 +143,7 @@ func S7VarPayloadDataItemParse(readBuffer utils.ReadBuffer, lastItem bool) (*S7V
 		if pullErr := readBuffer.PullContext("padding", utils.WithRenderAsList(true)); pullErr != nil {
 			return nil, pullErr
 		}
-		_timesPadding := (utils.InlineIf(lastItem, func() uint16 { return uint16(uint8(0)) }, func() uint16 { return uint16(uint8(uint8(len(data))) % uint8(uint8(2))) }))
+		_timesPadding := (utils.InlineIf(lastItem, func() interface{} { return uint8(uint8(0)) }, func() interface{} { return uint8(uint8(uint8(len(data))) % uint8(uint8(2))) }).(uint8))
 		for ; (readBuffer.HasMore(8)) && (_timesPadding > 0); _timesPadding-- {
 			// Just read the padding data and ignore it
 			_, _err := readBuffer.ReadUint8("", 8)
@@ -194,9 +194,9 @@ func (m *S7VarPayloadDataItem) Serialize(writeBuffer utils.WriteBuffer, lastItem
 	}
 
 	// Implicit Field (dataLength) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
-	dataLength := uint16(uint16(uint16(len(m.Data))) * uint16(uint16(utils.InlineIf(bool(bool((m.TransportSize) == (DataTransportSize_BIT))), func() uint16 { return uint16(uint16(1)) }, func() uint16 {
-		return uint16(uint16(utils.InlineIf(m.TransportSize.SizeInBits(), func() uint16 { return uint16(uint16(8)) }, func() uint16 { return uint16(uint16(1)) })))
-	}))))
+	dataLength := uint16(uint16(uint16(len(m.Data))) * uint16(uint16(utils.InlineIf(bool(bool((m.TransportSize) == (DataTransportSize_BIT))), func() interface{} { return uint16(uint16(1)) }, func() interface{} {
+		return uint16(uint16(utils.InlineIf(m.TransportSize.SizeInBits(), func() interface{} { return uint16(uint16(8)) }, func() interface{} { return uint16(uint16(1)) }).(uint16)))
+	}).(uint16))))
 	_dataLengthErr := writeBuffer.WriteUint16("dataLength", 16, (dataLength))
 	if _dataLengthErr != nil {
 		return errors.Wrap(_dataLengthErr, "Error serializing 'dataLength' field")
@@ -216,7 +216,7 @@ func (m *S7VarPayloadDataItem) Serialize(writeBuffer utils.WriteBuffer, lastItem
 		if pushErr := writeBuffer.PushContext("padding", utils.WithRenderAsList(true)); pushErr != nil {
 			return pushErr
 		}
-		_timesPadding := uint8(utils.InlineIf(lastItem, func() uint16 { return uint16(uint8(0)) }, func() uint16 { return uint16(uint8(uint8(len(m.Data))) % uint8(uint8(2))) }))
+		_timesPadding := uint8(utils.InlineIf(lastItem, func() interface{} { return uint8(uint8(0)) }, func() interface{} { return uint8(uint8(uint8(len(m.Data))) % uint8(uint8(2))) }).(uint8))
 		for ; _timesPadding > 0; _timesPadding-- {
 			_paddingValue := uint8(uint8(0))
 			_paddingErr := writeBuffer.WriteUint8("", 8, (_paddingValue))