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]) {