You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by jf...@apache.org on 2019/05/25 14:20:17 UTC
[plc4x] 01/02: [CODE-GEN] Several fixes and play around with ser /
deser.
This is an automated email from the ASF dual-hosted git repository.
jfeinauer pushed a commit to branch feature/code-gen-julian
in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit b24ee1c42fef1eafcfdc59b7e7dff7ec1dc9320e
Author: Julian Feinauer <j....@pragmaticminds.de>
AuthorDate: Fri May 24 14:52:00 2019 +0200
[CODE-GEN] Several fixes and play around with ser / deser.
---
pom.xml | 7 +
sandbox/plc4x-maven-plugin/pom.xml | 8 ++
.../plugins/codegenerator/parser/ClassBuilder.java | 147 +++++++++++++++++++++
.../parser/MessageFormatListener.java | 11 +-
.../codegenerator/parser/MessageFormatParser.java | 112 +++++++++++++++-
sandbox/pom.xml | 1 +
6 files changed, 280 insertions(+), 6 deletions(-)
diff --git a/pom.xml b/pom.xml
index d14ea55..17f70fc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -751,6 +751,13 @@
<!-- Temporary Python virtualenv files-->
<exclude>**/venv/**</exclude>
+
+ <!-- Exclude antlr4 files?! -->
+ <exclude>**/*.g4</exclude>
+
+
+ <!-- (Temporary) Exclude spec files (from Chris) -->
+ <exclude>**/*.spec</exclude>
</excludes>
</configuration>
</plugin>
diff --git a/sandbox/plc4x-maven-plugin/pom.xml b/sandbox/plc4x-maven-plugin/pom.xml
index ad9e8ca..d1a8121 100644
--- a/sandbox/plc4x-maven-plugin/pom.xml
+++ b/sandbox/plc4x-maven-plugin/pom.xml
@@ -213,6 +213,14 @@
</execution>
</executions>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>8</source>
+ <target>8</target>
+ </configuration>
+ </plugin>
</plugins>
</build>
diff --git a/sandbox/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/parser/ClassBuilder.java b/sandbox/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/parser/ClassBuilder.java
new file mode 100644
index 0000000..079fd4a
--- /dev/null
+++ b/sandbox/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/parser/ClassBuilder.java
@@ -0,0 +1,147 @@
+package org.apache.plc4x.plugins.codegenerator.parser;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Util to Define Classes based on the {@link org.apache.plc4x.codegen.ast.Expressions} API.
+ *
+ * @author julian
+ */
+public class ClassBuilder {
+
+ private String className;
+ private final List<ConstantField> constants = new ArrayList<>();
+ private final List<VariableField> fields = new ArrayList<>();
+ // TODO constructor call??
+ private String parent;
+
+ public ClassBuilder() {
+ }
+
+ public ClassBuilder withName(String name) {
+ className = name;
+ return this;
+ }
+
+ public ClassBuilder withConstant(String name, String type, Object value) {
+ this.constants.add(new ConstantField(name, type, value));
+ return this;
+ }
+
+ public ClassBuilder withConstant(String name, String type, Object value, Documentation docu) {
+ this.constants.add(new ConstantField(name, type, value, docu));
+ return this;
+ }
+
+ public ClassBuilder withField(String name, String type) {
+ this.fields.add(new VariableField(name, type));
+ return this;
+ }
+
+ public ClassBuilder withField(String name, String type, Documentation docu) {
+ this.fields.add(new VariableField(name, type, Optional.empty(), docu));
+ return this;
+ }
+
+ public ClassBuilder withField(String name, String type, Object initialValue, Documentation docu) {
+ this.fields.add(new VariableField(name, type, Optional.of(initialValue), docu));
+ return this;
+ }
+
+ public ClassBuilder withParent(String parent) {
+ this.parent = parent;
+ return this;
+ }
+
+ @Override public String toString() {
+ return "ClassBuilder{" +
+ "className='" + className + '\'' +
+ ", constants=" + constants +
+ ", fields=" + fields +
+ ", parent='" + parent + '\'' +
+ '}';
+ }
+
+ // Regular "java" fields
+ public static class VariableField {
+
+ private final String name;
+ private final String type;
+ private final Optional<Object> initialValue;
+ private final Documentation documentation;
+
+ public VariableField(String name, String type) {
+ this(name, type, Optional.empty(), null);
+ }
+
+ public VariableField(String name, String type, Optional<Object> initialValue) {
+ this(name, type, initialValue, null);
+ }
+
+ public VariableField(String name, String type, Optional<Object> initialValue, Documentation documentation) {
+ this.name = name;
+ this.type = type;
+ this.initialValue = initialValue;
+ this.documentation = documentation;
+ }
+
+ @Override public String toString() {
+ return "VariableField{" +
+ "name='" + name + '\'' +
+ ", type='" + type + '\'' +
+ ", initialValue=" + initialValue +
+ ", documentation=" + documentation +
+ '}';
+ }
+ }
+
+ // Consts
+ public static class ConstantField {
+
+ private final String name;
+ private final String type;
+ private final Object value;
+ private final Documentation documentation;
+
+ public ConstantField(String name, String type, Object value) {
+ this(name, type, value, null);
+ }
+
+ public ConstantField(String name, String type, Object value, Documentation documentation) {
+ this.name = name;
+ this.type = type;
+ this.value = value;
+ this.documentation = documentation;
+ }
+
+ @Override public String toString() {
+ return "ConstantField{" +
+ "name='" + name + '\'' +
+ ", type='" + type + '\'' +
+ ", value=" + value +
+ ", documentation=" + documentation +
+ '}';
+ }
+ }
+
+ /**
+ * Documentation for a declaration
+ */
+ public static class Documentation {
+
+ private final String text;
+
+ public Documentation(String text) {
+ this.text = text;
+ }
+
+ @Override public String toString() {
+ return "Documentation{" +
+ "text='" + text + '\'' +
+ '}';
+ }
+ }
+
+}
diff --git a/sandbox/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/parser/MessageFormatListener.java b/sandbox/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/parser/MessageFormatListener.java
index e0d0d01..c0211bc 100644
--- a/sandbox/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/parser/MessageFormatListener.java
+++ b/sandbox/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/parser/MessageFormatListener.java
@@ -72,7 +72,7 @@ public class MessageFormatListener extends ImaginaryBaseListener {
@Override
public void enterArrayField(ImaginaryParser.ArrayFieldContext ctx) {
String typeName = ctx.type.getText();
- String name = ctx.name.id.getText();
+ String name = ctx.name.IDENTIFIER().getText();
ArrayField.LengthType lengthType;
if(ctx.lengthType.K_COUNT() != null) {
lengthType = ArrayField.LengthType.COUNT;
@@ -87,7 +87,8 @@ public class MessageFormatListener extends ImaginaryBaseListener {
@Override
public void enterConstField(ImaginaryParser.ConstFieldContext ctx) {
SimpleType type = new SimpleType(ctx.type.getText());
- String expected = ctx.expected.getText();
+ // TODO use a visitor or something to get this without TICKs
+ String expected = ctx.expected.expr.getText();
Field field = new ConstField(type, expected);
parserContexts.peek().add(field);
}
@@ -115,7 +116,7 @@ public class MessageFormatListener extends ImaginaryBaseListener {
@Override
public void enterSimpleField(ImaginaryParser.SimpleFieldContext ctx) {
SimpleType type = new SimpleType(ctx.type.getText());
- String name = ctx.name.getText();
+ String name = ctx.name.IDENTIFIER().getText();
Field field = new SimpleField(type, name);
parserContexts.peek().add(field);
}
@@ -123,7 +124,7 @@ public class MessageFormatListener extends ImaginaryBaseListener {
@Override
public void enterImplicitField(ImaginaryParser.ImplicitFieldContext ctx) {
SimpleType type = new SimpleType(ctx.type.getText());
- String serializationExpression = ctx.serializationExpression.getText();
+ String serializationExpression = ctx.serializationExpression.innerExpression().getText();
Field field = new ImplicitField(type, serializationExpression);
parserContexts.peek().add(field);
}
@@ -131,7 +132,7 @@ public class MessageFormatListener extends ImaginaryBaseListener {
@Override
public void enterOptionalField(ImaginaryParser.OptionalFieldContext ctx) {
SimpleType type = new SimpleType(ctx.type.getText());
- String name = ctx.name.getText();
+ String name = ctx.name.IDENTIFIER().getText();
String conditionExpression = ctx.condition.expr.getText();
Field field = new OptionalField(type, name, conditionExpression);
parserContexts.peek().add(field);
diff --git a/sandbox/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/parser/MessageFormatParser.java b/sandbox/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/parser/MessageFormatParser.java
index df88a0a..9fa4f3c 100644
--- a/sandbox/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/parser/MessageFormatParser.java
+++ b/sandbox/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/parser/MessageFormatParser.java
@@ -23,18 +23,64 @@ import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
+import org.apache.plc4x.codegen.ast.ClassDeclaration;
+import org.apache.plc4x.codegen.ast.CodeWriter;
+import org.apache.plc4x.codegen.ast.Expressions;
+import org.apache.plc4x.codegen.ast.Generator;
+import org.apache.plc4x.codegen.ast.JavaGenerator;
+import org.apache.plc4x.codegen.ast.Primitive;
+import org.apache.plc4x.codegen.ast.TypeDefinition;
+import org.apache.plc4x.codegen.util.PojoFactory;
import org.apache.plc4x.codegenerator.parser.imaginary.ImaginaryLexer;
import org.apache.plc4x.codegenerator.parser.imaginary.ImaginaryParser;
import org.apache.plc4x.plugins.codegenerator.model.ComplexType;
+import org.apache.plc4x.plugins.codegenerator.model.DiscriminatedComplexType;
import org.apache.plc4x.plugins.codegenerator.model.Type;
+import org.apache.plc4x.plugins.codegenerator.model.fields.ArrayField;
+import org.apache.plc4x.plugins.codegenerator.model.fields.ConstField;
+import org.apache.plc4x.plugins.codegenerator.model.fields.DiscriminatorField;
+import org.apache.plc4x.plugins.codegenerator.model.fields.Field;
+import org.apache.plc4x.plugins.codegenerator.model.fields.ImplicitField;
+import org.apache.plc4x.plugins.codegenerator.model.fields.OptionalField;
+import org.apache.plc4x.plugins.codegenerator.model.fields.SimpleField;
+import org.apache.plc4x.plugins.codegenerator.model.fields.SwitchField;
import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
public class MessageFormatParser {
+ /**
+ * Turns parsed field into POJO Field.
+ * @param field
+ * @return
+ */
+ private static PojoFactory.Field fieldTranslator(Field field) {
+ if (field instanceof SimpleField) {
+ final String name = ((SimpleField) field).getName();
+ final Type type = ((SimpleField) field).getType();
+ return new PojoFactory.Field(Expressions.typeOf(type.getName()), name);
+ } else if (field instanceof ConstField) {
+ final Type type = ((ConstField) field).getType();
+ final Object value = ((ConstField) field).getReferenceValue();
+ return new PojoFactory.Field(Expressions.typeOf(type.getName()), "const_" + value);
+ } else if (field instanceof ImplicitField) {
+ final Type type = ((ImplicitField) field).getType();
+ final String expr = ((ImplicitField) field).getSerializationExpression();
+ return new PojoFactory.Field(Expressions.typeOf(type.getName()), "implicit_" + expr);
+ } else if (field instanceof OptionalField) {
+ final Type type = ((OptionalField) field).getType();
+ final String name = ((OptionalField) field).getName();
+ final String expr = ((OptionalField) field).getConditionExpression();
+ return new PojoFactory.Field(Expressions.typeOf(type.getName()), name + "?" + expr);
+ }
+ return new PojoFactory.Field(Primitive.VOID, "UNKNOWN_FIELD");
+ }
+
public List<Type> parse(InputStream source) {
try {
ImaginaryLexer lexer = new ImaginaryLexer(CharStreams.fromStream(source));
@@ -45,7 +91,71 @@ public class MessageFormatParser {
MessageFormatListener listener = new MessageFormatListener();
walker.walk(listener, tree);
Map<String, ComplexType> complexTypes = listener.getComplexTypes();
- System.out.println(complexTypes);
+ // System.out.println(complexTypes);
+ // Do a Pojo for everyone
+ final PojoFactory factory = new PojoFactory();
+ final List<ClassBuilder> classes = new ArrayList<>();
+ for (Map.Entry<String, ComplexType> entry : complexTypes.entrySet()) {
+ final CodeWriter writer = new CodeWriter(4);
+ final Generator generator = new JavaGenerator(writer);
+ System.out.println("// ----------------------");
+ System.out.println("// " + entry.getKey() + " ");
+ System.out.println("// ----------------------");
+
+ // Old Approach
+ final ComplexType type = entry.getValue();
+ final List<PojoFactory.Field> fields = type.getFields().stream()
+ .map(MessageFormatParser::fieldTranslator)
+ .collect(Collectors.toList());
+ final PojoFactory.PojoDescription pojoDesc = new PojoFactory.PojoDescription(entry.getKey(), fields);
+ final ClassDeclaration classDeclaration = factory.create(pojoDesc);
+ classDeclaration.write(generator);
+ // Output POJO
+ // System.out.println(writer.getCode());
+
+ // New Approach
+ final ClassBuilder classBuilder = new ClassBuilder();
+ classes.add(classBuilder);
+
+ classBuilder.withName(entry.getKey());
+ int constCount = 1;
+ int implicitCount = 1;
+ for (Field field : type.getFields()) {
+ if (field instanceof ArrayField) {
+ // do nothing
+ System.out.println("Skipping Array field...");
+ } else if (field instanceof ConstField) {
+ classBuilder.withConstant("CONST_" + constCount++, ((ConstField) field).getType().getName(), ((ConstField) field).getReferenceValue(), new ClassBuilder.Documentation("Constant expression"));
+ } else if (field instanceof SimpleField) {
+ classBuilder.withField(((SimpleField) field).getName(), ((SimpleField) field).getType().getName(), new ClassBuilder.Documentation("Simple Field..."));
+ } else if (field instanceof ImplicitField) {
+ classBuilder.withField("implicit" + implicitCount, ((ImplicitField) field).getType().getName(), ((ImplicitField) field).getSerializationExpression(), new ClassBuilder.Documentation("Implicitly defined field"));
+ } else if (field instanceof DiscriminatorField) {
+ classBuilder.withField(((DiscriminatorField) field).getName(), ((DiscriminatorField) field).getType().getName(), new ClassBuilder.Documentation("Discriminator Field..."));
+ } else if (field instanceof SwitchField) {
+ // Now do all "subtypes"
+ for (DiscriminatedComplexType aCase : ((SwitchField) field).getCases()) {
+ final ClassBuilder childBuilder = new ClassBuilder();
+ classes.add(childBuilder);
+ childBuilder.withName(aCase.getName());
+ childBuilder.withParent(entry.getKey());
+
+ }
+ } else if (field instanceof OptionalField) {
+ classBuilder.withField(((OptionalField) field).getName(), ((OptionalField) field).getType().getName(),
+ new ClassBuilder.Documentation("Optional field\n" + ((OptionalField) field).getConditionExpression()));
+ } else {
+ throw new RuntimeException("Fields of class " + field.getClass().getSimpleName() + " are not implemented yet!");
+ }
+ }
+
+ // System.out.println(classBuilder.toString());
+ }
+
+ // Now print all Classes
+ for (ClassBuilder aClass : classes) {
+ System.out.println(aClass.toString());
+ }
} catch (IOException e) {
throw new RuntimeException(e);
}
diff --git a/sandbox/pom.xml b/sandbox/pom.xml
index 424d01d..e4149dc 100644
--- a/sandbox/pom.xml
+++ b/sandbox/pom.xml
@@ -39,6 +39,7 @@
<module>dynamic-driver-knxnet-ip</module>
<module>dynamic-driver-s7</module>
<module>code-gen</module>
+ <module>plc4x-maven-plugin</module>
</modules>
</project>
\ No newline at end of file