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/03 14:54:03 UTC

[plc4x] branch feature/code-gen updated: - Fine-Tuning of the spec (correcting expressions, adding missing payload types to match the parameter types) - Added Array-Access to spec expressions - Made a "curPos" field available to the Jexl execution, if required - Fixed some errors in the MessageFormatListener not omitting the expression ticks - Made the plugin add the generated sources to the project sources (So they are compiled) - Implemented a first mostly working version of the ReadBuffer - Added a Test class to experiment wit [...]

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 fab6cb9  - Fine-Tuning of the spec (correcting expressions, adding missing payload types to match the parameter types) - Added Array-Access to spec expressions - Made a "curPos" field available to the Jexl execution, if required - Fixed some errors in the MessageFormatListener not omitting the expression ticks - Made the plugin add the generated sources to the project sources (So they are compiled) - Implemented a first mostly working version of the ReadBuffer - Added a Test clas [...]
fab6cb9 is described below

commit fab6cb944d47a81af08682d186c6de54046b5be7
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Mon Jun 3 16:53:54 2019 +0200

    - Fine-Tuning of the spec (correcting expressions, adding missing payload types to match the parameter types)
    - Added Array-Access to spec expressions
    - Made a "curPos" field available to the Jexl execution, if required
    - Fixed some errors in the MessageFormatListener not omitting the expression ticks
    - Made the plugin add the generated sources to the project sources (So they are compiled)
    - Implemented a first mostly working version of the ReadBuffer
    - Added a Test class to experiment with using the parser
---
 .../main/resources/templates/java/io-template.ftlh |   8 +-
 .../codegenerator/parser/imaginary/Imaginary.g4    |   1 +
 .../plc4x/plugins/codegenerator/GenerateMojo.java  |   3 +
 .../parser/MessageFormatListener.java              |   4 +-
 .../src/main/resources/protocols/s7/protocol.spec  |  10 +-
 .../code-generation/test-java-s7-driver/pom.xml    |  12 ++
 .../org/apache/plc4x/java/utils/ReadBuffer.java    | 155 +++++++++++++++++----
 .../org/apache/plc4x/java/utils/WriteBuffer.java   |  24 ++++
 .../test-java-s7-driver/src/test/java/Test.java    |  33 +++++
 9 files changed, 213 insertions(+), 37 deletions(-)

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 08f0364..fb45225 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
@@ -55,6 +55,7 @@ public class ${typeName}IO  {
     private static final Logger LOGGER = LoggerFactory.getLogger(${typeName}IO.class);
 
     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();
         JexlEngine jexl = new JexlBuilder().create();
         JexlContext jc = new MapContext();
         <#if type.parserArguments?has_content>
@@ -67,7 +68,10 @@ public class ${typeName}IO  {
 
         // Array field
         JexlExpression ex${field.name} = jexl.createExpression("${field.lengthExpression}");
-        int size = (int) ex${field.name}.evaluate(jc);
+        <#if field.lengthExpression?contains("curPos")>
+        jc.set("curPos", io.getPos() - startPos);
+        </#if>
+        int size = Integer.valueOf(ex${field.name}.evaluate(jc).toString());
         <#if helper.isCountArray(field)>
         ${helper.getLanguageTypeNameForSpecType(field.type)}[] ${field.name} = new ${helper.getLanguageTypeNameForSpecType(field.type)}[size];
         for(int i = 0; i < size; i++) {
@@ -147,7 +151,7 @@ public class ${typeName}IO  {
             builder = ${case.name}IO.parse(io<#if type.parserArguments?has_content>, <#list type.parserArguments as parserArgument>${parserArgument.name}<#sep>, </#sep></#list></#if>);
         }
         </#list>
-        else {
+        if (builder == null) {
             throw new ParseException("Unsupported case for discriminated type");
         }
         <#break>
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 9f84b82..4671814 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
@@ -107,6 +107,7 @@ innerExpression
  | IDENTIFIER   // Variable reference
  | innerExpression '.' IDENTIFIER // Field Reference
  | 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/GenerateMojo.java b/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/GenerateMojo.java
index f7a6432..516b789 100644
--- a/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/GenerateMojo.java
+++ b/sandbox/code-generation/plc4x-maven-plugin/src/main/java/org/apache/plc4x/plugins/codegenerator/GenerateMojo.java
@@ -136,6 +136,9 @@ public class GenerateMojo extends AbstractMojo {
         } catch (GenerationException e) {
             getLog().error("Error generating sources", e);
         }
+
+        // Add the generated sources to the project internally.
+        project.addCompileSourceRoot(outputDir.getPath());
     }
 
 }
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 9ef5847..be438b5 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
@@ -95,7 +95,7 @@ public class MessageFormatListener extends ImaginaryBaseListener {
         } else {
             lengthType = ArrayField.LengthType.LENGTH;
         }
-        String lengthExpression = ctx.lengthExpression.getText();
+        String lengthExpression = ctx.lengthExpression.expr.getText();
         String[] params = getFieldParams((ImaginaryParser.FieldDefinitionContext) ctx.parent.parent);
         Field field = new DefaultArrayField(type, name, lengthType, lengthExpression, params);
         parserContexts.peek().add(field);
@@ -140,7 +140,7 @@ 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.getText();
+        String serializationExpression = ctx.serializationExpression.expr.getText();
         Field field = new DefaultImplicitField(type, name, serializationExpression);
         parserContexts.peek().add(field);
     }
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 8e91b41..a84cdcb 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,7 +45,7 @@
             [field uint 8  'rejectCause']
         ]
     ]
-    [arrayField COTPParameter 'parameters' length '(headerLength + 1) - cur']
+    [arrayField COTPParameter 'parameters' length '(headerLength + 1) - curPos']
     [field      S7Message     'payload']
 ]
 
@@ -101,7 +101,7 @@
 [discriminatedType 'S7Parameter' [uint 8 'messageType']
     [discriminator uint 8 'parameterType']
     [typeSwitch 'parameterType','messageType'
-        ['0xF0' SetupCommunication
+        ['0xF0' S7ParameterSetupCommunication
             [reserved uint 8  '0x00']
             [field    uint 16 'maxAmqCaller']
             [field    uint 16 'maxAmqCallee']
@@ -144,7 +144,7 @@
         ['0x10' S7AddressAny
             [field    uint 8  'transportSize']
             [field    uint 16 'numberOfElements']
-            [field    uint 8  'dbNumber']
+            [field    uint 16 'dbNumber']
             [field    uint 8  'area']
             [reserved uint 5  '0x00']
             [field    uint 16 'byteAddress']
@@ -173,7 +173,9 @@
 // Payloads
 
 [discriminatedType 'S7Payload' [uint 8 'messageType', S7Parameter 'parameter']
-    [typeSwitch 'parameter.parameterType', 'messageType'
+    [typeSwitch 'parameter.discriminatorValues[0]', 'messageType'
+        ['0xF0' S7PayloadSetupCommunication]
+        ['0x04','0x01' S7PayloadReadVarRequest]
         ['0x04','0x03' S7PayloadReadVarResponse
             [arrayField S7VarPayloadDataItem 'items' count 'parameter.numItems']
         ]
diff --git a/sandbox/code-generation/test-java-s7-driver/pom.xml b/sandbox/code-generation/test-java-s7-driver/pom.xml
index 5665884..5933593 100644
--- a/sandbox/code-generation/test-java-s7-driver/pom.xml
+++ b/sandbox/code-generation/test-java-s7-driver/pom.xml
@@ -61,6 +61,18 @@
       <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>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+      <version>1.12</version>
+      <scope>test</scope>
+    </dependency>
 
     <dependency>
       <groupId>org.apache.plc4x.plugins</groupId>
diff --git a/sandbox/code-generation/test-java-s7-driver/src/main/java/org/apache/plc4x/java/utils/ReadBuffer.java b/sandbox/code-generation/test-java-s7-driver/src/main/java/org/apache/plc4x/java/utils/ReadBuffer.java
index 0524629..ff059dc 100644
--- a/sandbox/code-generation/test-java-s7-driver/src/main/java/org/apache/plc4x/java/utils/ReadBuffer.java
+++ b/sandbox/code-generation/test-java-s7-driver/src/main/java/org/apache/plc4x/java/utils/ReadBuffer.java
@@ -19,69 +19,166 @@
 
 package org.apache.plc4x.java.utils;
 
+import org.apache.commons.compress.utils.BitInputStream;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.nio.ByteOrder;
 
 public class ReadBuffer {
 
+    private BitInputStream bis;
+
+    
+    public ReadBuffer(byte[] input) {
+        ByteArrayInputStream bais = new ByteArrayInputStream(input);
+        bis = new BitInputStream(bais, ByteOrder.BIG_ENDIAN);
+    }
+
     public int getPos() {
-        return 0;
+        return (int) bis.getBytesRead();
     }
 
-    public boolean readBit() {
-        return false;
+    public boolean readBit() throws ParseException {
+        try {
+            return bis.readBits(1) == 1;
+        } catch (IOException e) {
+            throw new ParseException("Error reading", e);
+        }
     }
 
-    public byte readUnsignedByte(int bitLength) {
-        return 0;
+    public byte readUnsignedByte(int bitLength) throws ParseException {
+        if(bitLength <= 0) {
+            throw new ParseException("unsigned byte must contain at least 1 bit");
+        }
+        if(bitLength > 4) {
+            throw new ParseException("unsigned byte can only contain max 4 bits");
+        }
+        try {
+            return (byte) bis.readBits(bitLength);
+        } catch (IOException e) {
+            throw new ParseException("Error reading", e);
+        }
     }
 
-    public short readUnsignedShort(int bitLength) {
-        return 0;
+    public short readUnsignedShort(int bitLength) throws ParseException {
+        if(bitLength <= 0) {
+            throw new ParseException("unsigned short must contain at least 1 bit");
+        }
+        if(bitLength > 8) {
+            throw new ParseException("unsigned short can only contain max 8 bits");
+        }
+        try {
+            return (short) bis.readBits(bitLength);
+        } catch (IOException e) {
+            throw new ParseException("Error reading", e);
+        }
     }
 
-    public int readUnsignedInt(int bitLength) {
-        return 0;
+    public int readUnsignedInt(int bitLength) throws ParseException {
+        if(bitLength <= 0) {
+            throw new ParseException("unsigned int must contain at least 1 bit");
+        }
+        if(bitLength > 16) {
+            throw new ParseException("unsigned int can only contain max 16 bits");
+        }
+        try {
+            return (int) bis.readBits(bitLength);
+        } catch (IOException e) {
+            throw new ParseException("Error reading", e);
+        }
     }
 
-    public long readUnsignedLong(int bitLength) {
-        return 0;
+    public long readUnsignedLong(int bitLength) throws ParseException {
+        if(bitLength <= 0) {
+            throw new ParseException("unsigned long must contain at least 1 bit");
+        }
+        if(bitLength > 32) {
+            throw new ParseException("unsigned long can only contain max 32 bits");
+        }
+        try {
+            return bis.readBits(bitLength);
+        } catch (IOException e) {
+            throw new ParseException("Error reading", e);
+        }
     }
 
-    public BigInteger readUnsignedBigInteger(int bitLength) {
-        return BigInteger.ZERO;
+    public BigInteger readUnsignedBigInteger(int bitLength) throws ParseException {
+        throw new UnsupportedOperationException("not implemented yet");
     }
 
-    public byte readByte(int bitLength) {
-        return 0;
+    public byte readByte(int bitLength) throws ParseException {
+        if(bitLength <= 0) {
+            throw new ParseException("byte must contain at least 1 bit");
+        }
+        if(bitLength > 8) {
+            throw new ParseException("byte can only contain max 8 bits");
+        }
+        try {
+            return (byte) bis.readBits(bitLength);
+        } catch (IOException e) {
+            throw new ParseException("Error reading", e);
+        }
     }
 
-    public short readShort(int bitLength) {
-        return 0;
+    public short readShort(int bitLength) throws ParseException {
+        if(bitLength <= 0) {
+            throw new ParseException("short must contain at least 1 bit");
+        }
+        if(bitLength > 16) {
+            throw new ParseException("short can only contain max 16 bits");
+        }
+        try {
+            return (short) bis.readBits(bitLength);
+        } catch (IOException e) {
+            throw new ParseException("Error reading", e);
+        }
     }
 
-    public int readInt(int bitLength) {
-        return 0;
+    public int readInt(int bitLength) throws ParseException {
+        if(bitLength <= 0) {
+            throw new ParseException("int must contain at least 1 bit");
+        }
+        if(bitLength > 32) {
+            throw new ParseException("int can only contain max 32 bits");
+        }
+        try {
+            return (int) bis.readBits(bitLength);
+        } catch (IOException e) {
+            throw new ParseException("Error reading", e);
+        }
     }
 
-    public long readLong(int bitLength) {
-        return 0;
+    public long readLong(int bitLength) throws ParseException {
+        if(bitLength <= 0) {
+            throw new ParseException("long must contain at least 1 bit");
+        }
+        if(bitLength > 64) {
+            throw new ParseException("long can only contain max 64 bits");
+        }
+        try {
+            return bis.readBits(bitLength);
+        } catch (IOException e) {
+            throw new ParseException("Error reading", e);
+        }
     }
 
-    public BigInteger readBigInteger(int bitLength) {
-        return BigInteger.ZERO;
+    public BigInteger readBigInteger(int bitLength) throws ParseException {
+        throw new UnsupportedOperationException("not implemented yet");
     }
 
-    public float readFloat(int bitLength) {
-        return 0.0f;
+    public float readFloat(int bitLength) throws ParseException {
+        throw new UnsupportedOperationException("not implemented yet");
     }
 
-    public double readDouble(int bitLength) {
-        return 0.0;
+    public double readDouble(int bitLength) throws ParseException {
+        throw new UnsupportedOperationException("not implemented yet");
     }
 
-    public BigDecimal readBigDecimal(int bitLength) {
-        return BigDecimal.ZERO;
+    public BigDecimal readBigDecimal(int bitLength) throws ParseException {
+        throw new UnsupportedOperationException("not implemented yet");
     }
 
 }
diff --git a/sandbox/code-generation/test-java-s7-driver/src/main/java/org/apache/plc4x/java/utils/WriteBuffer.java b/sandbox/code-generation/test-java-s7-driver/src/main/java/org/apache/plc4x/java/utils/WriteBuffer.java
index 44aadf7..211239d 100644
--- a/sandbox/code-generation/test-java-s7-driver/src/main/java/org/apache/plc4x/java/utils/WriteBuffer.java
+++ b/sandbox/code-generation/test-java-s7-driver/src/main/java/org/apache/plc4x/java/utils/WriteBuffer.java
@@ -19,11 +19,35 @@
 
 package org.apache.plc4x.java.utils;
 
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 
 public class WriteBuffer {
 
+    private int bytePos;
+    private byte bitPos;
+    private ByteArrayOutputStream baos;
+    private DataOutputStream dos;
+
+    public WriteBuffer() {
+        bytePos = 0;
+        bitPos = 0;
+        baos = new ByteArrayOutputStream();
+        dos = new DataOutputStream(baos);
+    }
+
+    public byte[] getMessage() throws ParseException {
+        try {
+            dos.flush();
+        } catch (IOException e) {
+            throw new ParseException("Unable to flush buffer");
+        }
+        return baos.toByteArray();
+    }
+
     public void writeBit(boolean value) {
     }
 
diff --git a/sandbox/code-generation/test-java-s7-driver/src/test/java/Test.java b/sandbox/code-generation/test-java-s7-driver/src/test/java/Test.java
new file mode 100644
index 0000000..28598d5
--- /dev/null
+++ b/sandbox/code-generation/test-java-s7-driver/src/test/java/Test.java
@@ -0,0 +1,33 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+import org.apache.commons.codec.binary.Hex;
+import org.apache.plc4x.java.s7.TPKTPacket;
+import org.apache.plc4x.java.s7.io.TPKTPacketIO;
+import org.apache.plc4x.java.utils.ReadBuffer;
+
+public class Test {
+
+    public static void main(String[] args) throws Exception {
+        byte[] data = Hex.decodeHex("0300006702f080320100000001005600000407120a10060001032b84000160120a10020001032b840001a0120a10010001032b840001a9120a10050001032b84000150120a10020001032b84000198120a10040001032b84000140120a10020001032b84000190");
+        ReadBuffer buf = new ReadBuffer(data);
+        TPKTPacket packet = TPKTPacketIO.parse(buf);
+    }
+
+}