You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2019/06/16 09:30:32 UTC

[plc4x] branch feature/code-gen updated: - Refactored the code generator to use native java code instead of relying on an evaluation engine.

This is an automated email from the ASF dual-hosted git repository.

cdutz pushed a commit to branch feature/code-gen
in repository https://gitbox.apache.org/repos/asf/plc4x.git


The following commit(s) were added to refs/heads/feature/code-gen by this push:
     new 02aa40c  - Refactored the code generator to use native java code instead of relying on an evaluation engine.
02aa40c is described below

commit 02aa40c0b0c28ef258c048fa2189042f69cda221
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Sun Jun 16 11:30:21 2019 +0200

    - Refactored the code generator to use native java code instead of relying on an evaluation engine.
---
 .../language/expressions/terms/BinaryTerm.java     |   5 +
 .../language/expressions/terms/BooleanLiteral.java |   5 +
 .../language/expressions/terms/NullLiteral.java    |   5 +
 .../language/expressions/terms/NumericLiteral.java |   5 +
 .../language/expressions/terms/StringLiteral.java  |   5 +
 .../plc4x/language/expressions/terms/Term.java     |   2 +
 .../language/expressions/terms/TernaryTerm.java    |   5 +
 .../language/expressions/terms/UnaryTerm.java      |   5 +
 .../expressions/terms/VariableLiteral.java         |  25 ++-
 .../apache/plc4x/language/fields/ArrayField.java   |   4 +-
 .../apache/plc4x/language/fields/ConstField.java   |   6 +-
 .../plc4x/language/fields/DiscriminatorField.java  |   6 +-
 .../plc4x/language/fields/ImplicitField.java       |   8 +-
 .../plc4x/language/fields/OptionalField.java       |   4 +-
 .../plc4x/language/fields/PropertyField.java       |   6 +-
 .../plc4x/language/fields/ReservedField.java       |   6 +-
 .../fields/{PropertyField.java => TypedField.java} |   4 +-
 .../plc4x/language/java/JavaLanguageOutput.java    |   6 +-
 .../language/java/JavaLanguageTemplateHelper.java  | 204 ++++++++++++++++++++-
 .../main/resources/templates/java/io-template.ftlh | 138 +++++---------
 .../resources/templates/java/pojo-template.ftlh    |  37 +---
 sandbox/code-generation/plc4x-maven-plugin/pom.xml |  15 +-
 .../codegenerator/parser/expression/Expression.g4  |   6 +-
 .../codegenerator/parser/imaginary/Imaginary.g4    |   5 +-
 .../expression/ExpressionStringListener.java       |  14 +-
 .../model/fields/DefaultArrayField.java            |   7 +-
 .../model/fields/DefaultImplicitField.java         |   7 +-
 .../model/fields/DefaultOptionalField.java         |   7 +-
 .../parser/MessageFormatListener.java              |  23 ++-
 .../src/main/resources/protocols/s7/protocol.spec  |  22 +--
 .../code-generation/test-java-s7-driver/pom.xml    |  10 -
 .../src/test/java/BenchmarkGeneratedS7.java        |  15 +-
 32 files changed, 406 insertions(+), 216 deletions(-)

diff --git a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/BinaryTerm.java b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/BinaryTerm.java
index 4ee54a2..cbd9d50 100644
--- a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/BinaryTerm.java
+++ b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/BinaryTerm.java
@@ -43,4 +43,9 @@ public class BinaryTerm implements Term {
         return operation;
     }
 
+    @Override
+    public boolean contains(String str) {
+        return ((a != null) && a.contains(str)) || ((b != null) && b.contains(str));
+    }
+
 }
diff --git a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/BooleanLiteral.java b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/BooleanLiteral.java
index fe918dd..24753c5 100644
--- a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/BooleanLiteral.java
+++ b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/BooleanLiteral.java
@@ -31,4 +31,9 @@ public class BooleanLiteral implements Literal {
         return value;
     }
 
+    @Override
+    public boolean contains(String str) {
+        return false;
+    }
+
 }
diff --git a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/NullLiteral.java b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/NullLiteral.java
index 788f80e..c38bb49 100644
--- a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/NullLiteral.java
+++ b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/NullLiteral.java
@@ -24,4 +24,9 @@ public class NullLiteral implements Literal {
     public NullLiteral() {
     }
 
+    @Override
+    public boolean contains(String str) {
+        return false;
+    }
+
 }
diff --git a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/NumericLiteral.java b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/NumericLiteral.java
index 062509a..fc99dc8 100644
--- a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/NumericLiteral.java
+++ b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/NumericLiteral.java
@@ -31,4 +31,9 @@ public class NumericLiteral implements Literal {
         return number;
     }
 
+    @Override
+    public boolean contains(String str) {
+        return false;
+    }
+
 }
diff --git a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/StringLiteral.java b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/StringLiteral.java
index a6a40b2..1eb0068 100644
--- a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/StringLiteral.java
+++ b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/StringLiteral.java
@@ -31,4 +31,9 @@ public class StringLiteral implements Literal {
         return value;
     }
 
+    @Override
+    public boolean contains(String str) {
+        return (value != null) && value.contains(str);
+    }
+
 }
diff --git a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/Term.java b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/Term.java
index 4858be7..b4b9217 100644
--- a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/Term.java
+++ b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/Term.java
@@ -21,4 +21,6 @@ package org.apache.plc4x.language.expressions.terms;
 
 public interface Term {
 
+    boolean contains(String str);
+
 }
diff --git a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/TernaryTerm.java b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/TernaryTerm.java
index 7a34f3d..df34ee7 100644
--- a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/TernaryTerm.java
+++ b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/TernaryTerm.java
@@ -49,4 +49,9 @@ public class TernaryTerm implements Term {
         return operation;
     }
 
+    @Override
+    public boolean contains(String str) {
+        return ((a != null) && a.contains(str)) || ((b != null) && b.contains(str))  ||((c != null) && c.contains(str));
+    }
+
 }
diff --git a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/UnaryTerm.java b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/UnaryTerm.java
index 529c041..8094e30 100644
--- a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/UnaryTerm.java
+++ b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/UnaryTerm.java
@@ -37,4 +37,9 @@ public class UnaryTerm implements Term {
         return operation;
     }
 
+    @Override
+    public boolean contains(String str) {
+        return (a != null) && a.contains(str);
+    }
+
 }
diff --git a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/VariableLiteral.java b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/VariableLiteral.java
index cf2e330..a980ac1 100644
--- a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/VariableLiteral.java
+++ b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/expressions/terms/VariableLiteral.java
@@ -19,16 +19,20 @@
 
 package org.apache.plc4x.language.expressions.terms;
 
+import java.util.List;
+
 public class VariableLiteral implements Literal {
 
     public static final int NO_INDEX = -1;
 
     private final String name;
+    private final List<Term> args;
     private final int index;
     private final VariableLiteral child;
 
-    public VariableLiteral(String name, int index, VariableLiteral child) {
+    public VariableLiteral(String name, List<Term> args, int index, VariableLiteral child) {
         this.name = name;
+        this.args = args;
         this.index = index;
         this.child = child;
     }
@@ -37,6 +41,10 @@ public class VariableLiteral implements Literal {
         return name;
     }
 
+    public List<Term> getArgs() {
+        return args;
+    }
+
     public int getIndex() {
         return index;
     }
@@ -49,4 +57,19 @@ public class VariableLiteral implements Literal {
         return index != NO_INDEX;
     }
 
+    @Override
+    public boolean contains(String str) {
+        if(((name != null) && name.contains(str)) || ((child != null) && child.contains(str))) {
+            return true;
+        }
+        if(args != null) {
+            for(Term arg : args) {
+                if(arg.contains(str)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
 }
diff --git a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/ArrayField.java b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/ArrayField.java
index a0af838..b9042e1 100644
--- a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/ArrayField.java
+++ b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/ArrayField.java
@@ -20,6 +20,8 @@
 package org.apache.plc4x.language.fields;
 
 
+import org.apache.plc4x.language.expressions.terms.Term;
+
 public interface ArrayField extends PropertyField {
 
     default String getTypeName() {
@@ -28,7 +30,7 @@ public interface ArrayField extends PropertyField {
 
     LengthType getLengthType();
 
-    String getLengthExpression();
+    Term getLengthExpression();
 
     enum LengthType {
         COUNT,
diff --git a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/ConstField.java b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/ConstField.java
index e30b492..d1b6290 100644
--- a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/ConstField.java
+++ b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/ConstField.java
@@ -21,16 +21,12 @@ package org.apache.plc4x.language.fields;
 
 import org.apache.plc4x.language.references.TypeReference;
 
-public interface ConstField extends Field {
+public interface ConstField extends PropertyField {
 
     default String getTypeName() {
         return "const";
     }
 
-    TypeReference getType();
-
-    String getName();
-
     Object getReferenceValue();
 
 }
diff --git a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/DiscriminatorField.java b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/DiscriminatorField.java
index e8b3289..f725598 100644
--- a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/DiscriminatorField.java
+++ b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/DiscriminatorField.java
@@ -19,16 +19,12 @@
 
 package org.apache.plc4x.language.fields;
 
-import org.apache.plc4x.language.references.TypeReference;
-
-public interface DiscriminatorField extends Field {
+public interface DiscriminatorField extends TypedField {
 
     default String getTypeName() {
         return "discriminator";
     }
 
-    TypeReference getType();
-
     String getName();
 
 }
diff --git a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/ImplicitField.java b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/ImplicitField.java
index d631be9..283d777 100644
--- a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/ImplicitField.java
+++ b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/ImplicitField.java
@@ -19,18 +19,16 @@
 
 package org.apache.plc4x.language.fields;
 
-import org.apache.plc4x.language.references.TypeReference;
+import org.apache.plc4x.language.expressions.terms.Term;
 
-public interface ImplicitField extends Field {
+public interface ImplicitField extends TypedField {
 
     default String getTypeName() {
         return "implicit";
     }
 
-    TypeReference getType();
-
     String getName();
 
-    String getSerializationExpression();
+    Term getSerializationExpression();
 
 }
diff --git a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/OptionalField.java b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/OptionalField.java
index 7d0c60c..1ede08b 100644
--- a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/OptionalField.java
+++ b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/OptionalField.java
@@ -20,12 +20,14 @@
 package org.apache.plc4x.language.fields;
 
 
+import org.apache.plc4x.language.expressions.terms.Term;
+
 public interface OptionalField extends PropertyField {
 
     default String getTypeName() {
         return "optional";
     }
 
-    String getConditionExpression();
+    Term getConditionExpression();
 
 }
diff --git a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/PropertyField.java b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/PropertyField.java
index 167e43d..bda4a3e 100644
--- a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/PropertyField.java
+++ b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/PropertyField.java
@@ -19,11 +19,7 @@
 
 package org.apache.plc4x.language.fields;
 
-import org.apache.plc4x.language.references.TypeReference;
-
-public interface PropertyField extends Field {
-
-    TypeReference getType();
+public interface PropertyField extends TypedField {
 
     String getName();
 
diff --git a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/ReservedField.java b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/ReservedField.java
index 63e0759..e7644dd 100644
--- a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/ReservedField.java
+++ b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/ReservedField.java
@@ -19,16 +19,12 @@
 
 package org.apache.plc4x.language.fields;
 
-import org.apache.plc4x.language.references.TypeReference;
-
-public interface ReservedField extends Field {
+public interface ReservedField extends TypedField {
 
     default String getTypeName() {
         return "reserved";
     }
 
-    TypeReference getType();
-
     Object getReferenceValue();
 
 }
diff --git a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/PropertyField.java b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/TypedField.java
similarity index 92%
copy from sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/PropertyField.java
copy to sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/TypedField.java
index 167e43d..e170f6b 100644
--- a/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/PropertyField.java
+++ b/sandbox/code-generation/language-base/src/main/java/org/apache/plc4x/language/fields/TypedField.java
@@ -21,10 +21,8 @@ package org.apache.plc4x.language.fields;
 
 import org.apache.plc4x.language.references.TypeReference;
 
-public interface PropertyField extends Field {
+public interface TypedField extends Field {
 
     TypeReference getType();
 
-    String getName();
-
 }
diff --git a/sandbox/code-generation/language-template-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageOutput.java b/sandbox/code-generation/language-template-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageOutput.java
index 9f636fb..c30a6c9 100644
--- a/sandbox/code-generation/language-template-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageOutput.java
+++ b/sandbox/code-generation/language-template-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageOutput.java
@@ -60,7 +60,7 @@ public class JavaLanguageOutput implements LanguageOutput {
                 typeContext.put("packageName", packageName);
                 typeContext.put("typeName", typeEntry.getKey());
                 typeContext.put("type", typeEntry.getValue());
-                typeContext.put("helper", getHelper());
+                typeContext.put("helper", getHelper(types));
 
                 for(Template template : templateList) {
                     // Create a variable size output location where the template can generate it's content to
@@ -122,8 +122,8 @@ public class JavaLanguageOutput implements LanguageOutput {
             freemarkerConfiguration.getTemplate("templates/java/io-template.ftlh"));
     }
 
-    private JavaLanguageTemplateHelper getHelper() {
-        return new JavaLanguageTemplateHelper();
+    private JavaLanguageTemplateHelper getHelper(Map<String, ComplexTypeDefinition> types) {
+        return new JavaLanguageTemplateHelper(types);
     }
 
 }
diff --git a/sandbox/code-generation/language-template-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java b/sandbox/code-generation/language-template-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
index d57b64c..b8314e8 100644
--- a/sandbox/code-generation/language-template-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
+++ b/sandbox/code-generation/language-template-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
@@ -19,19 +19,88 @@
 
 package org.apache.plc4x.language.java;
 
+import com.sun.org.apache.xpath.internal.operations.Variable;
 import org.apache.commons.text.WordUtils;
+import org.apache.plc4x.language.definitions.ComplexTypeDefinition;
 import org.apache.plc4x.language.definitions.DiscriminatedComplexTypeDefinition;
 import org.apache.plc4x.language.definitions.TypeDefinition;
-import org.apache.plc4x.language.fields.ArrayField;
+import org.apache.plc4x.language.expressions.terms.*;
+import org.apache.plc4x.language.fields.*;
 import org.apache.plc4x.language.references.ComplexTypeReference;
 import org.apache.plc4x.language.references.SimpleTypeReference;
 import org.apache.plc4x.language.references.TypeReference;
 
+import java.util.Map;
+import java.util.function.Function;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 public class JavaLanguageTemplateHelper {
 
+    private final Map<String, ComplexTypeDefinition> types;
+
+    public JavaLanguageTemplateHelper(Map<String, ComplexTypeDefinition> types) {
+        this.types = types;
+    }
+
+    public String getLanguageTypeNameForField(TypedField field) {
+        boolean optional = field instanceof OptionalField;
+        TypeReference typeReference = field.getType();
+        if(typeReference instanceof SimpleTypeReference) {
+            SimpleTypeReference simpleTypeReference = (SimpleTypeReference) typeReference;
+            switch (simpleTypeReference.getBaseType()) {
+                case BIT: {
+                    return optional ? "Boolean" : "boolean";
+                }
+                case UINT: {
+                    if (simpleTypeReference.getSize() <= 4) {
+                        return optional ? "Byte" : "byte";
+                    }
+                    if (simpleTypeReference.getSize() <= 8) {
+                        return optional ? "Short" : "short";
+                    }
+                    if (simpleTypeReference.getSize() <= 16) {
+                        return optional ? "Integer" : "int";
+                    }
+                    if (simpleTypeReference.getSize() <= 32) {
+                        return optional ? "Long" : "long";
+                    }
+                    return "BigInteger";
+                }
+                case INT: {
+                    if (simpleTypeReference.getSize() <= 8) {
+                        return optional ? "Byte" : "byte";
+                    }
+                    if (simpleTypeReference.getSize() <= 16) {
+                        return optional ? "Short" : "short";
+                    }
+                    if (simpleTypeReference.getSize() <= 32) {
+                        return optional ? "Integer" : "int";
+                    }
+                    if (simpleTypeReference.getSize() <= 64) {
+                        return optional ? "Long" : "long";
+                    }
+                    return "BigInteger";
+                }
+                case FLOAT: {
+                    if (simpleTypeReference.getSize() <= 32) {
+                        return optional ? "Float" : "float";
+                    }
+                    if (simpleTypeReference.getSize() <= 64) {
+                        return optional ? "Double" : "double";
+                    }
+                    return "BigDecimal";
+                }
+                case STRING: {
+                    return "String";
+                }
+            }
+            return "Hurz";
+        } else {
+            return ((ComplexTypeReference) typeReference).getName();
+        }
+    }
+
     public String getLanguageTypeNameForSpecType(TypeReference typeReference) {
         if(typeReference instanceof SimpleTypeReference) {
             SimpleTypeReference simpleTypeReference = (SimpleTypeReference) typeReference;
@@ -132,6 +201,21 @@ public class JavaLanguageTemplateHelper {
         }
     }
 
+    public String getArgumentType(TypeReference typeReference, int index) {
+        if(typeReference instanceof ComplexTypeReference) {
+            ComplexTypeReference complexTypeReference = (ComplexTypeReference) typeReference;
+            if(!types.containsKey(complexTypeReference.getName())) {
+                throw new RuntimeException("Could not find definition of complex type " + complexTypeReference.getName());
+            }
+            ComplexTypeDefinition complexTypeDefinition = types.get(complexTypeReference.getName());
+            if(complexTypeDefinition.getParserArguments().length <= index) {
+                throw new RuntimeException("Type " + complexTypeReference.getName() + " specifies too few parser arguments");
+            }
+            return getLanguageTypeNameForSpecType(complexTypeDefinition.getParserArguments()[index].getType());
+        }
+        return "Hurz";
+    }
+
     public String getReadBufferReadMethodCall(SimpleTypeReference simpleTypeReference) {
         switch (simpleTypeReference.getBaseType()) {
             case BIT: {
@@ -257,7 +341,7 @@ public class JavaLanguageTemplateHelper {
         return arrayField.getLengthType() == ArrayField.LengthType.COUNT;
     }
 
-    public String toReadExpression(String expression) {
+    public String toSwitchExpression(String expression) {
         StringBuilder sb = new StringBuilder();
         Pattern pattern = Pattern.compile("([^\\.]*)\\.([a-zA-Z\\d]+)(.*)");
         Matcher matcher;
@@ -271,8 +355,120 @@ public class JavaLanguageTemplateHelper {
         return sb.toString();
     }
 
-    public String toWriteExpression(String expression) {
-        return expression;
+    public String toDeserializationExpression(Term term) {
+        return toExpression(term, this::toVariableDeserializationExpression);
+    }
+
+    public String toSerializationExpression(Term term) {
+        return toExpression(term, this::toVariableSerializationExpression);
+    }
+
+    private String toExpression(Term term, Function<Term, String> variableExpressionGenerator) {
+        if(term instanceof Literal) {
+            if(term instanceof NullLiteral) {
+                return "null";
+            } else if(term instanceof BooleanLiteral) {
+                return Boolean.toString(((BooleanLiteral) term).getValue());
+            } else if(term instanceof NumericLiteral) {
+                return ((NumericLiteral) term).getNumber().toString();
+            } else if(term instanceof StringLiteral) {
+                return "\"" + ((StringLiteral) term).getValue() + "\"";
+            } else if(term instanceof VariableLiteral) {
+                return variableExpressionGenerator.apply(term);
+            } else {
+                throw new RuntimeException("Unsupported Literal type " + term.getClass().getName());
+            }
+        } else if (term instanceof UnaryTerm) {
+            UnaryTerm ut = (UnaryTerm) term;
+            Term a = ut.getA();
+            switch(ut.getOperation()) {
+                case "!":
+                    return "!(" + toExpression(a, variableExpressionGenerator) + ")";
+                case "-":
+                    return "-(" + toExpression(a, variableExpressionGenerator) + ")";
+                case "()":
+                    return "(" + toExpression(a, variableExpressionGenerator) + ")";
+                default:
+                    throw new RuntimeException("Unsupported unary operation type " + ut.getOperation());
+            }
+        } else if (term instanceof BinaryTerm) {
+            BinaryTerm bt = (BinaryTerm) term;
+            Term a = bt.getA();
+            Term b = bt.getB();
+            String operation = bt.getOperation();
+            return "(" + toExpression(a, variableExpressionGenerator) + ") " + operation + " (" + toExpression(b, variableExpressionGenerator) + ")";
+        } else if (term instanceof TernaryTerm) {
+            TernaryTerm tt = (TernaryTerm) term;
+            if("if".equals(tt.getOperation())) {
+                Term a = tt.getA();
+                Term b = tt.getB();
+                Term c = tt.getC();
+                return "((" +  toExpression(a, variableExpressionGenerator) + ") ? " + toExpression(b, variableExpressionGenerator) + " : " + toExpression(c, variableExpressionGenerator) + ")";
+            } else {
+                throw new RuntimeException("Unsupported ternary operation type " + tt.getOperation());
+            }
+        } else {
+            throw new RuntimeException("Unsupported Term type " + term.getClass().getName());
+        }
+    }
+
+    private String toVariableDeserializationExpression(Term term) {
+        VariableLiteral vl = (VariableLiteral) term;
+        // CAST expressions are special as we need to add a ".class" to the second parameter in Java.
+        if("CAST".equals(vl.getName())) {
+            StringBuilder sb = new StringBuilder(vl.getName());
+            if((vl.getArgs() == null) || (vl.getArgs().size() != 2)) {
+                throw new RuntimeException("A CAST expression expects exactly two arguments.");
+            }
+            sb.append("(").append(toVariableDeserializationExpression(vl.getArgs().get(0)))
+                .append(", ").append(((VariableLiteral) vl.getArgs().get(1)).getName()).append(".class)");
+            return sb.toString() + ((vl.getChild() != null) ? "." + toVariableExpressionRest(vl.getChild()) : "");
+        }
+        // All uppercase names are not fields, but utility methods.
+        else if(vl.getName().equals(vl.getName().toUpperCase())) {
+            StringBuilder sb = new StringBuilder(vl.getName());
+            if(vl.getArgs() != null) {
+                sb.append("(");
+                boolean firstArg = true;
+                for(Term arg : vl.getArgs()) {
+                    if(!firstArg) {
+                        sb.append(", ");
+                    }
+                    sb.append(toVariableDeserializationExpression(arg));
+                    firstArg = false;
+                }
+                sb.append(")");
+            }
+            return sb.toString() + ((vl.getChild() != null) ? "." + toVariableExpressionRest(vl.getChild()) : "");
+        }
+        return vl.getName() + ((vl.getChild() != null) ? "." + toVariableExpressionRest(vl.getChild()) : "");
+    }
+
+    private String toVariableSerializationExpression(Term term) {
+        VariableLiteral vl = (VariableLiteral) term;
+        // All uppercase names are not fields, but utility methods.
+        if(vl.getName().equals(vl.getName().toUpperCase())) {
+            StringBuilder sb = new StringBuilder(vl.getName());
+            if(vl.getArgs() != null) {
+                sb.append("(");
+                boolean firstArg = true;
+                for(Term arg : vl.getArgs()) {
+                    if(!firstArg) {
+                        sb.append(", ");
+                    }
+                    sb.append(toVariableSerializationExpression(arg));
+                    firstArg = false;
+                }
+                sb.append(")");
+            }
+            return sb.toString();
+        }
+        return "value." + toVariableExpressionRest(vl);
+    }
+
+    private String toVariableExpressionRest(VariableLiteral vl) {
+        return "get" + WordUtils.capitalize(vl.getName()) + "()" + ((vl.isIndexed() ? "[" + vl.getIndex() + "]" : "") +
+            ((vl.getChild() != null) ? "." + toVariableExpressionRest(vl.getChild()) : ""));
     }
 
 }
diff --git a/sandbox/code-generation/language-template-java/src/main/resources/templates/java/io-template.ftlh b/sandbox/code-generation/language-template-java/src/main/resources/templates/java/io-template.ftlh
index 5b14c11..fef151d 100644
--- a/sandbox/code-generation/language-template-java/src/main/resources/templates/java/io-template.ftlh
+++ b/sandbox/code-generation/language-template-java/src/main/resources/templates/java/io-template.ftlh
@@ -39,7 +39,6 @@ ${packageName?replace(".", "/")}/io/${typeName}IO.java
 package ${packageName}.io;
 
 import ${packageName}.*;
-import org.apache.commons.jexl3.*;
 import org.apache.plc4x.java.utils.EvaluationHelper;
 import org.apache.plc4x.java.utils.ReadBuffer;
 import org.apache.plc4x.java.utils.ParseException;
@@ -48,6 +47,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -55,117 +55,66 @@ public class ${typeName}IO  {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(${typeName}IO.class);
 
-<#assign needJexl=false>
-<#list type.fields as field>
-<#switch field.typeName>
-    <#case "array">
-    private static JexlExpression ex${field.name?cap_first};
-    <#assign needJexl=true>
-    <#break>
-    <#case "optional">
-    private static JexlExpression ex${field.name?cap_first};
-    <#assign needJexl=true>
-    <#break>
-    <#case "implicit">
-    private static JexlExpression ex${field.name?cap_first};
-    <#assign needJexl=true>
-    <#break>
-</#switch>
-</#list>
-<#if needJexl>
-    private static JexlEngine jexl;
-    static {
-        jexl = new JexlBuilder().create();
-<#list type.fields as field>
-<#switch field.typeName>
-    <#case "array">
-        ex${field.name?cap_first} = jexl.createExpression("${field.lengthExpression}");
-        <#break>
-    <#case "optional">
-        ex${field.name?cap_first} = jexl.createExpression("${field.conditionExpression}");
-        <#break>
-    <#case "implicit">
-        ex${field.name?cap_first} = jexl.createExpression("${field.serializationExpression}");
-        <#break>
-</#switch>
-</#list>
-    }
-</#if>
-
     public static <#if helper.isDiscriminatedType(type)>${typeName}Builder<#else>${typeName}</#if> parse(ReadBuffer io<#if type.parserArguments?has_content>, <#list type.parserArguments as parserArgument>${helper.getLanguageTypeNameForSpecType(parserArgument.type)} ${parserArgument.name}<#sep>, </#sep></#list></#if>) throws ParseException {
         int startPos = io.getPos();
-<#if needJexl>
-        JexlContext jc = new MapContext();
-        <#if type.parserArguments?has_content>
-        <#list type.parserArguments as parserArgument>
-        jc.set("${parserArgument.name}", ${parserArgument.name});
-        </#list></#if>
-</#if>
+        int curPos;
 <#list type.fields as field>
 <#switch field.typeName>
     <#case "array">
 
         // Array field
-        <#if field.lengthExpression?contains("curPos")>
-        jc.set("curPos", io.getPos() - startPos);
+        <#if field.lengthExpression.contains("curPos")>
+        curPos = io.getPos() - startPos;
         </#if>
-        int size = Integer.valueOf(ex${field.name?cap_first}.evaluate(jc).toString());
+        int size = ${helper.toDeserializationExpression(field.lengthExpression)};
         <#if helper.isCountArray(field)>
-        ${helper.getLanguageTypeNameForSpecType(field.type)}[] ${field.name} = new ${helper.getLanguageTypeNameForSpecType(field.type)}[size];
+        ${helper.getLanguageTypeNameForField(field)}[] ${field.name} = new ${helper.getLanguageTypeNameForField(field)}[size];
         for(int i = 0; i < size; i++) {
             ${field.name}[i] = <#if helper.isSimpleType(field.type)>io.${helper.getReadBufferReadMethodCall(field.type)}<#else>${field.type.name}IO.parse(io<#if field.params?has_content>, <#list field.params as parserArgument>${parserArgument}<#sep>, </#sep></#list></#if>)</#if>;
         }
         <#else>
-        List<${helper.getLanguageTypeNameForSpecType(field.type)}> ${field.name}List = <#if helper.isCountArray(field)>new ArrayList<>(size)<#else>new LinkedList<>()</#if>;
+        List<${helper.getLanguageTypeNameForField(field)}> ${field.name}List = <#if helper.isCountArray(field)>new ArrayList<>(size)<#else>new LinkedList<>()</#if>;
         int endPos = io.getPos() + size;
         while(io.getPos() < endPos) {
-            ${field.name}List.add(<#if helper.isSimpleType(field.type)>io.${helper.getReadBufferReadMethodCall(field.type)}<#else>${field.type.name}IO.parse(io<#if field.params?has_content>, <#list field.params as parserArgument>${parserArgument}<#sep>, </#sep></#list></#if>)</#if>);
+            <#if field.lengthExpression.contains("curPos")>
+            curPos = io.getPos() - startPos;
+            </#if>
+            ${field.name}List.add(<#if helper.isSimpleType(field.type)>io.${helper.getReadBufferReadMethodCall(field.type)}<#else>${field.type.name}IO.parse(io<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getArgumentType(field.type, parserArgument?index)}) (${parserArgument})<#sep>, </#sep></#list></#if>)</#if>);
         }
-        ${helper.getLanguageTypeNameForSpecType(field.type)}[] ${field.name} = ${field.name}List.toArray(new ${helper.getLanguageTypeNameForSpecType(field.type)}[0]);
+        ${helper.getLanguageTypeNameForField(field)}[] ${field.name} = ${field.name}List.toArray(new ${helper.getLanguageTypeNameForField(field)}[0]);
         </#if>
-        jc.set("${field.name}", ${field.name});
         <#break>
     <#case "const">
 
         // Const Field
-        ${helper.getLanguageTypeNameForSpecType(field.type)} ${field.name} = io.${helper.getReadMethodName(field.type)}(${field.type.size});
+        ${helper.getLanguageTypeNameForField(field)} ${field.name} = io.${helper.getReadMethodName(field.type)}(${field.type.size});
         if(${field.name} != ${typeName}.${field.name?upper_case}) {
             throw new ParseException("Expected constant value " + ${typeName}.${field.name?upper_case} + " but got " + ${field.name});
         }
-<#if needJexl>
-        jc.set("${field.name}", ${field.name});
-</#if>
         <#break>
     <#case "discriminator">
 
         // Discriminator Field (Used as input to a switch field)
-        ${helper.getLanguageTypeNameForSpecType(field.type)} ${field.name} = io.${helper.getReadMethodName(field.type)}(${field.type.size});
-<#if needJexl>
-        jc.set("${field.name}", ${field.name});
-</#if>
+        ${helper.getLanguageTypeNameForField(field)} ${field.name} = io.${helper.getReadMethodName(field.type)}(${field.type.size});
     <#break>
     <#case "implicit">
 
         // Implicit Field (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
-        ${helper.getLanguageTypeNameForSpecType(field.type)} ${field.name} = io.${helper.getReadMethodName(field.type)}(${field.type.size});
-<#if needJexl>
-        jc.set("${field.name}", ${field.name});
-</#if>
+        ${helper.getLanguageTypeNameForField(field)} ${field.name} = io.${helper.getReadMethodName(field.type)}(${field.type.size});
         <#break>
     <#case "optional">
 
         // Optional Field (Can be skipped, if a given expression evaluates to false)
-        ${helper.getLanguageTypeNameForSpecType(field.type)} ${field.name} = ${helper.getNullValueForType(field.type)};
-        if(ex${field.name?cap_first}.evaluate(jc) == Boolean.TRUE) {
+        ${helper.getLanguageTypeNameForField(field)} ${field.name} = ${helper.getNullValueForType(field.type)};
+        if(${helper.toDeserializationExpression(field.conditionExpression)}) {
             ${field.name} = <#if helper.isSimpleType(field.type)>io.${helper.getReadBufferReadMethodCall(field.type)}<#else>${field.type.name}IO.parse(io);</#if>;
         }
-        jc.set("${field.name}", ${field.name});
         <#break>
     <#case "reserved">
 
         // Reserved Field (Compartmentalized so the "reserved" variable can't leak)
         {
-            ${helper.getLanguageTypeNameForSpecType(field.type)} reserved = io.${helper.getReadMethodName(field.type)}(${field.type.size});
+            ${helper.getLanguageTypeNameForField(field)} reserved = io.${helper.getReadMethodName(field.type)}(${field.type.size});
             if(reserved != ${field.referenceValue}) {
                 LOGGER.info("Expected constant value " + ${field.referenceValue} + " but got " + reserved + " for reserved field.");
             }
@@ -174,17 +123,14 @@ public class ${typeName}IO  {
     <#case "simple">
 
         // Simple field
-        ${helper.getLanguageTypeNameForSpecType(field.type)} ${field.name} = <#if helper.isSimpleType(field.type)>io.${helper.getReadBufferReadMethodCall(field.type)}<#else>${field.type.name}IO.parse(io<#if field.params?has_content>, <#list field.params as parserArgument>${parserArgument}<#sep>, </#sep></#list></#if>)</#if>;
-<#if needJexl>
-        jc.set("${field.name}", ${field.name});
-</#if>
+        ${helper.getLanguageTypeNameForField(field)} ${field.name} = <#if helper.isSimpleType(field.type)>io.${helper.getReadBufferReadMethodCall(field.type)}<#else>${field.type.name}IO.parse(io<#if field.params?has_content>, <#list field.params as parserArgument>${parserArgument}<#sep>, </#sep></#list></#if>)</#if>;
         <#break>
     <#case "switch">
 
         // Switch field (Depending on the discriminator values, passes the instantiation to a sub-type)
         ${typeName}Builder builder = null;
         <#list field.cases as case>
-        if(<#list case.discriminatorValues as discriminatorValue>EvaluationHelper.equals(${helper.toReadExpression(field.discriminatorNames[discriminatorValue?index])}, ${discriminatorValue})<#sep> && </#sep></#list>) {
+        if(<#list case.discriminatorValues as discriminatorValue>EvaluationHelper.equals(${helper.toSwitchExpression(field.discriminatorNames[discriminatorValue?index])}, ${discriminatorValue})<#sep> && </#sep></#list>) {
             builder = ${case.name}IO.parse(io<#if type.parserArguments?has_content>, <#list type.parserArguments as parserArgument>${parserArgument.name}<#sep>, </#sep></#list></#if>);
         }<#sep> else </#sep>
         </#list>
@@ -206,20 +152,17 @@ public class ${typeName}IO  {
     }
 
     public static void serialize(WriteBuffer io, ${typeName} value) throws ParseException {
-<#if needJexl>
-        JexlContext jc = new ObjectContext<>(jexl, value);
-</#if>
 <#list type.fields as field>
 <#switch field.typeName>
     <#case "array">
 
         // Array field
         if(value.get${field.name?cap_first}() != null) {
-            for(${helper.getLanguageTypeNameForSpecType(field.type)} element : value.get${field.name?cap_first}()) {
+            for(${helper.getLanguageTypeNameForField(field)} element : value.get${field.name?cap_first}()) {
                 <#if helper.isSimpleType(field.type)>
                 io.${helper.getWriteBufferReadMethodCall(field.type, "element")};
                 <#else>
-                ${helper.getLanguageTypeNameForSpecType(field.type)}IO.serialize(io, element);
+                ${helper.getLanguageTypeNameForField(field)}IO.serialize(io, element);
                 </#if>
             }
         }
@@ -241,16 +184,16 @@ public class ${typeName}IO  {
     <#case "implicit">
 
         // Implicit Field (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
-        io.${helper.getWriteBufferReadMethodCall(field.type, "ex" + field.name?cap_first + ".evaluate(jc)")};
+        io.${helper.getWriteBufferReadMethodCall(field.type, "(" + helper.toSerializationExpression(field.serializationExpression) + ")")};
         <#break>
     <#case "optional">
 
-        // Optional Field (Can be skipped, if a given expression evaluates to false)
-        if(ex${field.name?cap_first}.evaluate(jc) == Boolean.TRUE) {
+        // Optional Field (Can be skipped, if the value is null)
+        if(value.get${field.name?cap_first}() != null) {
             <#if helper.isSimpleType(field.type)>
             io.${helper.getWriteBufferReadMethodCall(field.type, "value.get" + field.name?cap_first + "()")};
             <#else>
-            ${helper.getLanguageTypeNameForSpecType(field.type)}IO.serialize(io, value.get${field.name?cap_first}());
+            ${helper.getLanguageTypeNameForField(field)}IO.serialize(io, value.get${field.name?cap_first}());
             </#if>
         }
         <#break>
@@ -265,7 +208,7 @@ public class ${typeName}IO  {
         <#if helper.isSimpleType(field.type)>
         io.${helper.getWriteBufferReadMethodCall(field.type, "value.get" + field.name?cap_first + "()")};
         <#else>
-        ${helper.getLanguageTypeNameForSpecType(field.type)}IO.serialize(io, value.get${field.name?cap_first}());
+        ${helper.getLanguageTypeNameForField(field)}IO.serialize(io, value.get${field.name?cap_first}());
         </#if>
         <#break>
     <#case "switch">
@@ -281,9 +224,28 @@ public class ${typeName}IO  {
 </#list>
     }
 
+    private static int COUNT(Object obj) {
+        if(obj.getClass().isArray()) {
+            Object[] arr = (Object[]) obj;
+            return arr.length;
+        } else if(obj instanceof Collection) {
+            Collection col = (Collection) obj;
+            return col.size();
+        }
+        throw new RuntimeException("Unable to count object of type " + obj.getClass().getName());
+    }
+
+    private static <T> T CAST(Object obj, Class<T> clazz) {
+        try {
+            return clazz.cast(obj);
+        } catch(ClassCastException e) {
+            throw new RuntimeException("Unable to cast object of type " + obj.getClass().getName() + " to " + clazz.getName());
+        }
+    }
+
 <#if type.abstract>
     public static interface ${typeName}Builder {
-        ${typeName} build(<#list type.propertyFields as field>${helper.getLanguageTypeNameForSpecType(field.type)}<#if field.lengthType??>[]</#if> ${field.name}<#sep>, </#sep></#list>);
+        ${typeName} build(<#list type.propertyFields as field>${helper.getLanguageTypeNameForField(field)}<#if field.lengthType??>[]</#if> ${field.name}<#sep>, </#sep></#list>);
     }
 
 </#if>
@@ -291,17 +253,17 @@ public class ${typeName}IO  {
     public static class ${typeName}Builder implements ${type.parentType.name}IO.${type.parentType.name}Builder {
         <#if type.propertyFields?has_content>
         <#list type.propertyFields as field>
-        private final ${helper.getLanguageTypeNameForSpecType(field.type)}<#if field.lengthType??>[]</#if> ${field.name};
+        private final ${helper.getLanguageTypeNameForField(field)}<#if field.lengthType??>[]</#if> ${field.name};
         </#list>
         </#if>
 
-        public ${typeName}Builder(<#list type.propertyFields as field>${helper.getLanguageTypeNameForSpecType(field.type)}<#if field.lengthType??>[]</#if> ${field.name}<#sep>, </#sep></#list>) {
+        public ${typeName}Builder(<#list type.propertyFields as field>${helper.getLanguageTypeNameForField(field)}<#if field.lengthType??>[]</#if> ${field.name}<#sep>, </#sep></#list>) {
             <#list type.propertyFields as field>
             this.${field.name} = ${field.name};
             </#list>
         }
 
-        public ${typeName} build(<#list type.parentType.propertyFields as field>${helper.getLanguageTypeNameForSpecType(field.type)}<#if field.lengthType??>[]</#if> ${field.name}<#sep>, </#sep></#list>) {
+        public ${typeName} build(<#list type.parentType.propertyFields as field>${helper.getLanguageTypeNameForField(field)}<#if field.lengthType??>[]</#if> ${field.name}<#sep>, </#sep></#list>) {
             return new ${typeName}(<#list type.getAllPropertyFields() as field>${field.name}<#sep>, </#sep></#list>);
         }
     }
diff --git a/sandbox/code-generation/language-template-java/src/main/resources/templates/java/pojo-template.ftlh b/sandbox/code-generation/language-template-java/src/main/resources/templates/java/pojo-template.ftlh
index 3548b27..75279ff 100644
--- a/sandbox/code-generation/language-template-java/src/main/resources/templates/java/pojo-template.ftlh
+++ b/sandbox/code-generation/language-template-java/src/main/resources/templates/java/pojo-template.ftlh
@@ -38,34 +38,10 @@ ${packageName?replace(".", "/")}/${typeName}.java
 
 package ${packageName};
 
-import org.apache.commons.jexl3.*;
 import org.apache.plc4x.java.utils.SizeAware;
 
 public<#if type.abstract> abstract</#if> class ${typeName}<#if type.parentType??> extends ${type.parentType.name}</#if> implements SizeAware {
 
-<#assign needJexl=false>
-<#list type.fields as field>
-<#switch field.typeName>
-    <#case "optional">
-    private static JexlExpression ex${field.name?cap_first};
-    <#assign needJexl=true>
-    <#break>
-</#switch>
-</#list>
-<#if needJexl>
-    private static JexlEngine jexl;
-    static {
-    jexl = new JexlBuilder().create();
-<#list type.fields as field>
-<#switch field.typeName>
-    <#case "optional">
-    ex${field.name?cap_first} = jexl.createExpression("${field.conditionExpression}");
-    <#break>
-</#switch>
-</#list>
-    }
-</#if>
-
 <#if helper.isDiscriminatedType(type)>
 
     // Discriminator values used by the parser to determine the type to be used. All values have to apply.
@@ -79,18 +55,18 @@ public<#if type.abstract> abstract</#if> class ${typeName}<#if type.parentType??
 
     // Constant values.
 <#list type.constFields as field>
-    public static final ${helper.getLanguageTypeNameForSpecType(field.type)} ${field.name?upper_case} = ${field.referenceValue};
+    public static final ${helper.getLanguageTypeNameForField(field)} ${field.name?upper_case} = ${field.referenceValue};
 </#list>
 </#if>
 <#if type.propertyFields?has_content>
 
     // Properties.
 <#list type.propertyFields as field>
-    private final ${helper.getLanguageTypeNameForSpecType(field.type)}<#if field.lengthType??>[]</#if> ${field.name};
+    private final ${helper.getLanguageTypeNameForField(field)}<#if field.lengthType??>[]</#if> ${field.name};
 </#list>
 </#if>
 
-    public ${typeName}(<#list type.getAllPropertyFields() as field>${helper.getLanguageTypeNameForSpecType(field.type)}<#if field.lengthType??>[]</#if> ${field.name}<#sep>, </#sep></#list>) {
+    public ${typeName}(<#list type.getAllPropertyFields() as field>${helper.getLanguageTypeNameForField(field)}<#if field.lengthType??>[]</#if> ${field.name}<#sep>, </#sep></#list>) {
 <#if type.getParentPropertyFields()?has_content>
         super(<#list type.getParentPropertyFields() as field>${field.name}<#sep>, </#sep></#list>);
 </#if>
@@ -110,16 +86,13 @@ public<#if type.abstract> abstract</#if> class ${typeName}<#if type.parentType??
 </#if>
 
 <#list type.propertyFields as field>
-    public ${helper.getLanguageTypeNameForSpecType(field.type)}<#if field.lengthType??>[]</#if> get${field.name?cap_first}() {
+    public ${helper.getLanguageTypeNameForField(field)}<#if field.lengthType??>[]</#if> get${field.name?cap_first}() {
         return ${field.name};
     }
 
 </#list>
     @Override
     public int getLengthInBytes() {
-<#if needJexl>
-        JexlContext jc = new ObjectContext<>(jexl, this);
-</#if>
         int lengthInBits = <#if type.parentType??>super.getLengthInBytes() * 8<#else>0</#if>;
 <#list type.fields as field>
 <#switch field.typeName>
@@ -152,7 +125,7 @@ public<#if type.abstract> abstract</#if> class ${typeName}<#if type.parentType??
     <#case "optional">
 
         // Optional Field (${field.name})
-        if(ex${field.name?cap_first}.evaluate(jc) == Boolean.TRUE) {
+        if(${field.name} != null) {
             lengthInBits += ${field.type.size};
         }
         <#break>
diff --git a/sandbox/code-generation/plc4x-maven-plugin/pom.xml b/sandbox/code-generation/plc4x-maven-plugin/pom.xml
index 343de65..02b9d11 100644
--- a/sandbox/code-generation/plc4x-maven-plugin/pom.xml
+++ b/sandbox/code-generation/plc4x-maven-plugin/pom.xml
@@ -44,16 +44,6 @@
       <artifactId>plc4x-code-generation-protocol-base</artifactId>
       <version>1.0.0-SNAPSHOT</version>
     </dependency>
-    <!--dependency>
-      <groupId>org.apache.commons</groupId>
-      <artifactId>commons-text</artifactId>
-      <version>1.4</version>
-    </dependency-->
-    <!--dependency>
-      <groupId>org.apache.plc4x.sandbox</groupId>
-      <artifactId>code-gen</artifactId>
-      <version>0.4.0-SNAPSHOT</version>
-    </dependency-->
 
     <dependency>
       <groupId>org.antlr</groupId>
@@ -65,6 +55,11 @@
       <artifactId>commons-beanutils</artifactId>
       <version>1.9.3</version>
     </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>2.6</version>
+    </dependency>
 
     <dependency>
       <groupId>org.apache.maven</groupId>
diff --git a/sandbox/code-generation/plc4x-maven-plugin/src/main/antlr4/org/apache/plc4x/codegenerator/parser/expression/Expression.g4 b/sandbox/code-generation/plc4x-maven-plugin/src/main/antlr4/org/apache/plc4x/codegenerator/parser/expression/Expression.g4
index 9e022f3..663bec2 100644
--- a/sandbox/code-generation/plc4x-maven-plugin/src/main/antlr4/org/apache/plc4x/codegenerator/parser/expression/Expression.g4
+++ b/sandbox/code-generation/plc4x-maven-plugin/src/main/antlr4/org/apache/plc4x/codegenerator/parser/expression/Expression.g4
@@ -24,7 +24,11 @@ expression
  ;
 
 identifierSegment
- : name=Identifier index=indexes? ('.' rest=identifierSegment)?
+ : name=Identifier args=arguments? index=indexes? ('.' rest=identifierSegment)?
+ ;
+
+arguments
+ : '(' (expression (',' expression)*)? ')'
  ;
 
 indexes
diff --git a/sandbox/code-generation/plc4x-maven-plugin/src/main/antlr4/org/apache/plc4x/codegenerator/parser/imaginary/Imaginary.g4 b/sandbox/code-generation/plc4x-maven-plugin/src/main/antlr4/org/apache/plc4x/codegenerator/parser/imaginary/Imaginary.g4
index 1448442..c87c136 100644
--- a/sandbox/code-generation/plc4x-maven-plugin/src/main/antlr4/org/apache/plc4x/codegenerator/parser/imaginary/Imaginary.g4
+++ b/sandbox/code-generation/plc4x-maven-plugin/src/main/antlr4/org/apache/plc4x/codegenerator/parser/imaginary/Imaginary.g4
@@ -117,10 +117,9 @@ multipleExpressions
 innerExpression
  : HEX_LITERAL
  | INTEGER_LITERAL
- | IDENTIFIER '()'?   // Variable reference or method call
- | innerExpression '.' IDENTIFIER '()'? // Field Reference or method call
+ | (IDENTIFIER | arrayType) ('(' (innerExpression (',' innerExpression)* )? ')')? ('[' innerExpression ']')?
+ | innerExpression '.' innerExpression // Field Reference or method call
  | innerExpression BinaryOperator innerExpression  // Addition
- | innerExpression LBRACKET INTEGER_LITERAL RBRACKET
  | '(' innerExpression ')'
  | '"' innerExpression '"'
  ;
diff --git a/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/expression/ExpressionStringListener.java b/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/expression/ExpressionStringListener.java
index 444c507..b9e8f45 100644
--- a/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/expression/ExpressionStringListener.java
+++ b/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/expression/ExpressionStringListener.java
@@ -82,8 +82,14 @@ public class ExpressionStringListener extends ExpressionBaseListener {
     }
 
     @Override
+    public void enterIdentifierExpression(ExpressionParser.IdentifierExpressionContext ctx) {
+        parserContexts.push(new LinkedList<>());
+    }
+
+    @Override
     public void exitIdentifierExpression(ExpressionParser.IdentifierExpressionContext ctx) {
-        parserContexts.peek().add(getVariableLiteral(ctx.identifierSegment()));
+        List<Term> args = parserContexts.pop();
+        parserContexts.peek().add(getVariableLiteral(ctx.identifierSegment(), args));
     }
 
     /////////////////////////////////////////////////////////////////////////////////////////
@@ -223,11 +229,11 @@ public class ExpressionStringListener extends ExpressionBaseListener {
     // Helpers
     /////////////////////////////////////////////////////////////////////////////////////////
 
-    private VariableLiteral getVariableLiteral(ExpressionParser.IdentifierSegmentContext ctx) {
+    private VariableLiteral getVariableLiteral(ExpressionParser.IdentifierSegmentContext ctx, List<Term> args) {
         String name = ctx.name.getText();
         int index = (ctx.index != null) ? Integer.valueOf(ctx.index.getText()) : VariableLiteral.NO_INDEX;
-        VariableLiteral child = (ctx.rest != null) ? getVariableLiteral(ctx.rest) : null;
-        return new VariableLiteral(name, index, child);
+        VariableLiteral child = (ctx.rest != null) ? getVariableLiteral(ctx.rest, args) : null;
+        return new VariableLiteral(name, args, index, child);
     }
 
     private UnaryTerm getUnaryTerm(String op, List<Term> terms) {
diff --git a/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/model/fields/DefaultArrayField.java b/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/model/fields/DefaultArrayField.java
index b2b9d54..2a8485c 100644
--- a/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/model/fields/DefaultArrayField.java
+++ b/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/model/fields/DefaultArrayField.java
@@ -19,6 +19,7 @@
 
 package org.apache.plc4x.plugins.codegenerator.model.fields;
 
+import org.apache.plc4x.language.expressions.terms.Term;
 import org.apache.plc4x.language.fields.ArrayField;
 import org.apache.plc4x.language.references.TypeReference;
 
@@ -27,10 +28,10 @@ public class DefaultArrayField implements ArrayField {
     private final TypeReference type;
     private final String name;
     private final ArrayField.LengthType lengthType;
-    private final String lengthExpression;
+    private final Term lengthExpression;
     private final String[] params;
 
-    public DefaultArrayField(TypeReference type, String name, ArrayField.LengthType lengthType, String lengthExpression, String[] params) {
+    public DefaultArrayField(TypeReference type, String name, ArrayField.LengthType lengthType, Term lengthExpression, String[] params) {
         this.type = type;
         this.name = name;
         this.lengthType = lengthType;
@@ -50,7 +51,7 @@ public class DefaultArrayField implements ArrayField {
         return lengthType;
     }
 
-    public String getLengthExpression() {
+    public Term getLengthExpression() {
         return lengthExpression;
     }
 
diff --git a/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/model/fields/DefaultImplicitField.java b/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/model/fields/DefaultImplicitField.java
index 719c64d..0769db5 100644
--- a/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/model/fields/DefaultImplicitField.java
+++ b/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/model/fields/DefaultImplicitField.java
@@ -19,6 +19,7 @@
 
 package org.apache.plc4x.plugins.codegenerator.model.fields;
 
+import org.apache.plc4x.language.expressions.terms.Term;
 import org.apache.plc4x.language.fields.ImplicitField;
 import org.apache.plc4x.language.references.TypeReference;
 
@@ -26,9 +27,9 @@ public class DefaultImplicitField implements ImplicitField {
 
     private final TypeReference type;
     private final String name;
-    private final String serializationExpression;
+    private final Term serializationExpression;
 
-    public DefaultImplicitField(TypeReference type, String name, String serializationExpression) {
+    public DefaultImplicitField(TypeReference type, String name, Term serializationExpression) {
         this.type = type;
         this.name = name;
         this.serializationExpression = serializationExpression;
@@ -42,7 +43,7 @@ public class DefaultImplicitField implements ImplicitField {
         return name;
     }
 
-    public String getSerializationExpression() {
+    public Term getSerializationExpression() {
         return serializationExpression;
     }
 
diff --git a/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/model/fields/DefaultOptionalField.java b/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/model/fields/DefaultOptionalField.java
index 2735425..1734fc3 100644
--- a/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/model/fields/DefaultOptionalField.java
+++ b/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/model/fields/DefaultOptionalField.java
@@ -19,6 +19,7 @@
 
 package org.apache.plc4x.plugins.codegenerator.model.fields;
 
+import org.apache.plc4x.language.expressions.terms.Term;
 import org.apache.plc4x.language.fields.OptionalField;
 import org.apache.plc4x.language.references.TypeReference;
 
@@ -26,10 +27,10 @@ public class DefaultOptionalField implements OptionalField {
 
     private final TypeReference type;
     private final String name;
-    private final String conditionExpression;
+    private final Term conditionExpression;
     private final String[] params;
 
-    public DefaultOptionalField(TypeReference type, String name, String conditionExpression, String[] params) {
+    public DefaultOptionalField(TypeReference type, String name, Term conditionExpression, String[] params) {
         this.type = type;
         this.name = name;
         this.conditionExpression = conditionExpression;
@@ -44,7 +45,7 @@ public class DefaultOptionalField implements OptionalField {
         return name;
     }
 
-    public String getConditionExpression() {
+    public Term getConditionExpression() {
         return conditionExpression;
     }
 
diff --git a/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/parser/MessageFormatListener.java b/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/parser/MessageFormatListener.java
index 001888c..f2b098b 100644
--- a/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/parser/MessageFormatListener.java
+++ b/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/parser/MessageFormatListener.java
@@ -19,9 +19,11 @@
 
 package org.apache.plc4x.plugins.codegenerator.parser;
 
+import org.apache.commons.io.IOUtils;
 import org.apache.plc4x.codegenerator.parser.imaginary.ImaginaryBaseListener;
 import org.apache.plc4x.codegenerator.parser.imaginary.ImaginaryParser;
 import org.apache.plc4x.language.definitions.Argument;
+import org.apache.plc4x.language.expressions.terms.Term;
 import org.apache.plc4x.language.fields.ArrayField;
 import org.apache.plc4x.language.fields.Field;
 import org.apache.plc4x.language.fields.SwitchField;
@@ -29,12 +31,14 @@ import org.apache.plc4x.language.references.SimpleTypeReference;
 import org.apache.plc4x.language.references.TypeReference;
 import org.apache.plc4x.language.definitions.ComplexTypeDefinition;
 import org.apache.plc4x.language.definitions.DiscriminatedComplexTypeDefinition;
+import org.apache.plc4x.plugins.codegenerator.expression.ExpressionStringParser;
 import org.apache.plc4x.plugins.codegenerator.model.definitions.DefaultComplexTypeDefinition;
 import org.apache.plc4x.plugins.codegenerator.model.definitions.DefaultDiscriminatedComplexTypeDefinition;
 import org.apache.plc4x.plugins.codegenerator.model.references.DefaultComplexTypeReference;
 import org.apache.plc4x.plugins.codegenerator.model.references.DefaultSimpleTypeReference;
 import org.apache.plc4x.plugins.codegenerator.model.fields.*;
 
+import java.io.InputStream;
 import java.util.*;
 
 public class MessageFormatListener extends ImaginaryBaseListener {
@@ -95,7 +99,10 @@ public class MessageFormatListener extends ImaginaryBaseListener {
         } else {
             lengthType = ArrayField.LengthType.LENGTH;
         }
-        String lengthExpression = ctx.lengthExpression.expr.getText();
+        String lengthExpressionString = ctx.lengthExpression.expr.getText();
+        InputStream inputStream = IOUtils.toInputStream(lengthExpressionString);
+        ExpressionStringParser parser = new ExpressionStringParser();
+        Term lengthExpression =  parser.parse(inputStream);
         String[] params = getFieldParams((ImaginaryParser.FieldDefinitionContext) ctx.parent.parent);
         Field field = new DefaultArrayField(type, name, lengthType, lengthExpression, params);
         parserContexts.peek().add(field);
@@ -131,7 +138,10 @@ public class MessageFormatListener extends ImaginaryBaseListener {
     public void enterImplicitField(ImaginaryParser.ImplicitFieldContext ctx) {
         SimpleTypeReference type = getSimpleTypeReference(ctx.type);
         String name = ctx.name.id.getText();
-        String serializationExpression = ctx.serializationExpression.expr.getText();
+        String serializationExpressionString = ctx.serializationExpression.expr.getText();
+        InputStream inputStream = IOUtils.toInputStream(serializationExpressionString);
+        ExpressionStringParser parser = new ExpressionStringParser();
+        Term serializationExpression =  parser.parse(inputStream);
         Field field = new DefaultImplicitField(type, name, serializationExpression);
         parserContexts.peek().add(field);
     }
@@ -140,7 +150,10 @@ public class MessageFormatListener extends ImaginaryBaseListener {
     public void enterOptionalField(ImaginaryParser.OptionalFieldContext ctx) {
         TypeReference type = getTypeReference(ctx.type);
         String name = ctx.name.id.getText();
-        String conditionExpression = ctx.condition.expr.getText();
+        String conditionExpressionString = ctx.condition.expr.getText();
+        InputStream inputStream = IOUtils.toInputStream(conditionExpressionString);
+        ExpressionStringParser parser = new ExpressionStringParser();
+        Term conditionExpression =  parser.parse(inputStream);
         String[] params = getFieldParams((ImaginaryParser.FieldDefinitionContext) ctx.parent.parent);
         Field field = new DefaultOptionalField(type, name, conditionExpression, params);
         parserContexts.peek().add(field);
@@ -262,4 +275,8 @@ public class MessageFormatListener extends ImaginaryBaseListener {
         return params;
     }
 
+    private Term parseExpression(String expressionString) {
+        return null;
+    }
+
 }
diff --git a/sandbox/code-generation/protocol-s7/src/main/resources/protocols/s7/protocol.spec b/sandbox/code-generation/protocol-s7/src/main/resources/protocols/s7/protocol.spec
index 18bcab0..c53b26b 100644
--- a/sandbox/code-generation/protocol-s7/src/main/resources/protocols/s7/protocol.spec
+++ b/sandbox/code-generation/protocol-s7/src/main/resources/protocols/s7/protocol.spec
@@ -45,11 +45,11 @@
             [field uint 8  'rejectCause']
         ]
     ]
-    [arrayField COTPParameter 'parameters' length '(headerLength + 1) - curPos']
+    [arrayField COTPParameter 'parameters' length '(headerLength + 1) - curPos' ['(headerLength + 1) - curPos']]
     [field      S7Message     'payload']
 ]
 
-[discriminatedType 'COTPParameter'
+[discriminatedType 'COTPParameter' [uint 8 'rest']
     [discriminator uint 8 'parameterType']
     [typeSwitch 'parameterType'
         ['0xC0' COTPParameterTpduSize
@@ -108,21 +108,21 @@
             [field    uint 16 'pduLength']
         ]
         ['0x04','0x01' S7ParameterReadVarRequest
-            [implicit   uint 8                    'numItems' 'items.size()']
+            [implicit   uint 8                    'numItems' 'COUNT(items)']
             [arrayField S7VarRequestParameterItem 'items'    count 'numItems']
         ]
         ['0x04','0x03' S7ParameterReadVarResponse
             [field uint 8 'numItems']
         ]
         ['0x05','0x01' S7ParameterWriteVarRequest
-            [implicit   uint 8                    'numItems' 'items.size()']
+            [implicit   uint 8                    'numItems' 'COUNT(items)']
             [arrayField S7VarRequestParameterItem 'items'    count 'numItems']
         ]
         ['0x05','0x03' S7ParameterWriteVarResponse
             [field uint 8 'numItems']
         ]
         ['0x00','0x07' S7ParameterUserData
-            [implicit   uint 8       'numItems' 'items.size()']
+            [implicit   uint 8       'numItems' 'COUNT(items)']
             [arrayField UserDataItem 'items' count 'numItems']
         ]
     ]
@@ -162,9 +162,9 @@
             [field         uint 16 'cpuFunctionType']
             [field         uint 8  'subFunctionGroup']
             [field         uint 8  'sequenceNumber']
-            [optionalField uint 8  'dataUnitReferenceNumber' 'lengthInBytes == 8']
-            [optionalField uint 8  'lastDataUnit' 'lengthInBytes == 8']
-            [optionalField uint 8  'errorCode' 'lengthInBytes == 8']
+            [optionalField uint 8  'dataUnitReferenceNumber' 'parameterLength == 8']
+            [optionalField uint 8  'lastDataUnit' 'parameterLength == 8']
+            [optionalField uint 8  'errorCode' 'parameterLength == 8']
         ]
     ]
 ]
@@ -177,13 +177,13 @@
         ['0xF0' S7PayloadSetupCommunication]
         ['0x04','0x01' S7PayloadReadVarRequest]
         ['0x04','0x03' S7PayloadReadVarResponse
-            [arrayField S7VarPayloadDataItem 'items' count 'parameter.numItems']
+            [arrayField S7VarPayloadDataItem 'items' count 'CAST(parameter, S7ParameterReadVarResponse).numItems']
         ]
         ['0x05','0x01' S7PayloadWriteVarRequest
-            [arrayField S7VarPayloadDataItem 'items' count 'parameter.numItems']
+            [arrayField S7VarPayloadDataItem 'items' count 'COUNT(CAST(parameter, S7ParameterWriteVarRequest).items)']
         ]
         ['0x05','0x03' S7PayloadWriteVarResponse
-            [arrayField S7VarPayloadStatusItem 'items' count 'parameter.numItems']
+            [arrayField S7VarPayloadStatusItem 'items' count 'CAST(parameter, S7ParameterWriteVarResponse).numItems']
         ]
         ['0x00','0x07' S7PayloadUserData
         ]
diff --git a/sandbox/code-generation/test-java-s7-driver/pom.xml b/sandbox/code-generation/test-java-s7-driver/pom.xml
index b1ca6bf..615ce5c 100644
--- a/sandbox/code-generation/test-java-s7-driver/pom.xml
+++ b/sandbox/code-generation/test-java-s7-driver/pom.xml
@@ -57,16 +57,6 @@
 
   <dependencies>
     <dependency>
-      <groupId>org.apache.commons</groupId>
-      <artifactId>commons-jexl3</artifactId>
-      <version>3.1</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.commons</groupId>
-      <artifactId>commons-compress</artifactId>
-      <version>1.18</version>
-    </dependency>
-    <dependency>
       <groupId>com.github.jinahya</groupId>
       <artifactId>bit-io</artifactId>
       <version>1.4.2</version>
diff --git a/sandbox/code-generation/test-java-s7-driver/src/test/java/BenchmarkGeneratedS7.java b/sandbox/code-generation/test-java-s7-driver/src/test/java/BenchmarkGeneratedS7.java
index a0a7fb3..1a17925 100644
--- a/sandbox/code-generation/test-java-s7-driver/src/test/java/BenchmarkGeneratedS7.java
+++ b/sandbox/code-generation/test-java-s7-driver/src/test/java/BenchmarkGeneratedS7.java
@@ -31,30 +31,31 @@ public class BenchmarkGeneratedS7 {
                                     //        00
         byte[] rData = Hex.decodeHex("0300006702f080320100000001005600000407120a10060001032b84000160120a10020001032b840001a0120a10010001032b840001a9120a10050001032b84000150120a10020001032b84000198120a10040001032b84000140120a10020001032b84000190");
         long start = System.currentTimeMillis();
-        int numRuns = 1;
+        int numRunsParse = 2000000£;
 
         // Benchmark the parsing code
         TPKTPacket packet = null;
-        for(int i = 0; i < numRuns; i++) {
+        for(int i = 0; i < numRunsParse; i++) {
             ReadBuffer rBuf = new ReadBuffer(rData);
             packet = TPKTPacketIO.parse(rBuf);
         }
         long endParsing = System.currentTimeMillis();
 
-        System.out.println("Parsed " + numRuns + " packets in " + (endParsing - start) + "ms");
-        System.out.println("That's " + ((float) (endParsing - start) / numRuns) + "ms per packet");
+        System.out.println("Parsed " + numRunsParse + " packets in " + (endParsing - start) + "ms");
+        System.out.println("That's " + ((float) (endParsing - start) / numRunsParse) + "ms per packet");
 
         // Benchmark the serializing code
+        int numRunsSerailze = 2000000;
         byte[] oData = null;
-        for(int i = 0; i < numRuns; i++) {
+        for(int i = 0; i < numRunsSerailze; i++) {
             WriteBuffer wBuf = new WriteBuffer(packet.getLengthInBytes());
             TPKTPacketIO.serialize(wBuf, packet);
             oData = wBuf.getData();
         }
         long endSerializing = System.currentTimeMillis();
 
-        System.out.println("Serialized " + numRuns + " packets in " + (endSerializing - endParsing) + "ms");
-        System.out.println("That's " + ((float) (endSerializing - endParsing) / numRuns) + "ms per packet");
+        System.out.println("Serialized " + numRunsSerailze + " packets in " + (endSerializing - endParsing) + "ms");
+        System.out.println("That's " + ((float) (endSerializing - endParsing) / numRunsSerailze) + "ms per packet");
         if(!Arrays.equals(rData, oData)) {
             for(int i = 0; i < rData.length; i++) {
                 if(rData[i] != oData[i]) {