You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2019/12/06 15:07:57 UTC

[plc4x] branch feature/ams_ads_mpsec updated (0ea2303 -> 0e28841)

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

sruehl pushed a change to branch feature/ams_ads_mpsec
in repository https://gitbox.apache.org/repos/asf/plc4x.git.


 discard 0ea2303  added bitmask and possibility to add comments at more places
 discard 0443734  added test for parent expression
 discard 393e134  added parent expressionn
 discard 00568b9  cleanup tests and reformat code
 discard 468cfb0  added some tests for expression parser and WIP for MFL and MFP
 discard 3ed19c6  initial ams/ads mspec
     add 9d141e1  - Fixed a problem that if an Iso on TCP packet didn't start with "0x03" then it wouldn't remove that byte and the driver would go into an infinite loop.
     add 7d73e38  Added station/address parameter to AB-ETH driver
     add deb7aa6  - Updated the fake kafka-connect config to one that matches other examples running in our IoT Lab
     new e40253f  initial ams/ads mspec
     new c76ff54  added some tests for expression parser and WIP for MFL and MFP
     new 877319f  cleanup tests and reformat code
     new f3c6f86  added parent expressionn
     new 836638f  added test for parent expression
     new 94907da  added bitmask and possibility to add comments at more places
     new 0e28841  cleanup and remove byte type

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (0ea2303)
            \
             N -- N -- N   refs/heads/feature/ams_ads_mpsec (0e28841)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 7 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../plugins/codegenerator/language/mspec/MSpec.g4  |  1 -
 .../src/test/resources/mspec.example               |  4 +-
 .../org/apache/plc4x/java/abeth/AbEthDriver.java   |  8 ++--
 .../java/abeth/connection/AbEthPlcConnection.java  | 16 ++++----
 .../apache/plc4x/java/abeth/model/AbEthField.java  |  7 ++--
 .../java/abeth/protocol/Plc4xAbEthProtocol.java    |  8 ++--
 plc4j/examples/hello-world-plc4x/pom.xml           |  7 ++++
 .../apache-kafka/config/plc4x-source.properties    | 48 +++++++++++-----------
 .../java/isoontcp/protocol/IsoOnTcpProtocol.java   | 10 +++++
 pom.xml                                            |  2 +-
 .../main/resources/protocols/amsads/amsads.mspec   | 30 +++++++-------
 src/site/asciidoc/protocols/ab-eth/index.adoc      |  2 +-
 src/site/asciidoc/protocols/features.adoc          |  8 ++++
 src/site/site.xml                                  |  1 +
 14 files changed, 91 insertions(+), 61 deletions(-)


[plc4x] 07/07: cleanup and remove byte type

Posted by sr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch feature/ams_ads_mpsec
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 0e28841470b1ce29107fe9d11e3f26bfa6ca5c4a
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Dec 6 16:07:42 2019 +0100

    cleanup and remove byte type
---
 .../plugins/codegenerator/language/mspec/MSpec.g4  |  1 -
 .../src/test/resources/mspec.example               |  4 +--
 pom.xml                                            |  2 +-
 .../main/resources/protocols/amsads/amsads.mspec   | 30 ++++++++++++----------
 4 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4 b/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4
index b37751c..5161ba7 100644
--- a/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4
+++ b/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4
@@ -139,7 +139,6 @@ caseStatement
 
 dataType
  : base='bit'
- | base='byte' size=INTEGER_LITERAL
  | base='int' size=INTEGER_LITERAL
  | base='uint' size=INTEGER_LITERAL
  | base='float' size=INTEGER_LITERAL
diff --git a/build-utils/protocol-base-mspec/src/test/resources/mspec.example b/build-utils/protocol-base-mspec/src/test/resources/mspec.example
index 51bed3d..8d24525 100644
--- a/build-utils/protocol-base-mspec/src/test/resources/mspec.example
+++ b/build-utils/protocol-base-mspec/src/test/resources/mspec.example
@@ -38,7 +38,7 @@
     [implicit   uint        32  'dataLength'        '../data.lengthInBytes' ]
     [simple     uint        32  'errorCode'                                 ]
     // free usable field of 4 bytes
-    [simple     byte        32  'invokeId'                                  ]
+    [array      uint        32  'invokeId'                                  ]
 ]
 
 [enum uint 16 'CommandId'
@@ -54,7 +54,7 @@
     ['0x09' ADS_READ_WRITE]
 ]
 
-[bitmask byte 2 'State'
+[bitmask uint 16 'State'
     ['0b0000_0000_0000_0001' RESPONSE]
     ['0b0000_0000_0000_0010' NO_RETURN]
     ['0b0000_0000_0000_0100' ADS_COMMAND]
diff --git a/pom.xml b/pom.xml
index 46f76f9..efb7a2e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -103,7 +103,7 @@
     <!-- Exclude all generated code -->
     <sonar.exclusions>**/generated-sources</sonar.exclusions>
 
-    <plc4x-code-generation.version>1.1.0-SNAPSHOT</plc4x-code-generation.version>
+    <plc4x-code-generation.version>1.0.0</plc4x-code-generation.version>
 
     <antlr.version>4.7.2</antlr.version>
     <asm.version>5.0.4</asm.version>
diff --git a/protocols/amsads/src/main/resources/protocols/amsads/amsads.mspec b/protocols/amsads/src/main/resources/protocols/amsads/amsads.mspec
index 8f22167..aa2aeda 100644
--- a/protocols/amsads/src/main/resources/protocols/amsads/amsads.mspec
+++ b/protocols/amsads/src/main/resources/protocols/amsads/amsads.mspec
@@ -22,22 +22,23 @@
 ////////////////////////////////////////////////////////////////
 
 [type 'AMSPacket'
-    [reserved   uint       16       '0x0000'                                             ]
-    [implicit   uint       32       'length' 'header.lengthInBytes + data.lengthInBytes' ]
-    [simple     AMSHeader  'header'                                                      ]
-    [simple     ADSData    'data'                                                        ]
+    [reserved   uint       16       '0x0000'                                                   ]
+    [implicit   uint       32       'packetLength' 'header.lengthInBytes + data.lengthInBytes' ]
+    [simple     AMSHeader  'header'                                                            ]
+    [simple     ADSData    'data'                                                              ]
 ]
 
 [type 'AMSHeader'
-    [simple     AMSNetId        'targetAmsNetId'        ]
-    [simple     uint        16  'targetAmsPort'         ]
-    [simple     AMSNetId        'sourceAmsNetId'        ]
-    [simple     uint        16  'sourceAmsPort'         ]
-    [enum       CommandId       'commandId'             ]
-    [bitmask    State           'state'                 ]
-    [simple     uint        32  '../data.lengthInBytes' ]
-    [simple     uint        32  'errorCode'             ]
-    [simple     byte        32  'invokeId'              ]
+    [simple     AMSNetId        'targetAmsNetId'                            ]
+    [simple     uint        16  'targetAmsPort'                             ]
+    [simple     AMSNetId        'sourceAmsNetId'                            ]
+    [simple     uint        16  'sourceAmsPort'                             ]
+    [enum       CommandId       'commandId'                                 ]
+    [bitmask    State           'state'                                     ]
+    [implicit   uint        32  'dataLength'        '../data.lengthInBytes' ]
+    [simple     uint        32  'errorCode'                                 ]
+    // free usable field of 4 bytes
+    [array     byte         4  'invokeId'                                  ]
 ]
 
 [enum uint 16 'CommandId'
@@ -76,5 +77,6 @@
 
 [type 'ADSData'
    // TODO: implement me..... arrrrrrrggggggggggggg
-   ....
+   //....
+   [simple     uint        8   'random'            ]
 ]
\ No newline at end of file


[plc4x] 02/07: added some tests for expression parser and WIP for MFL and MFP

Posted by sr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch feature/ams_ads_mpsec
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit c76ff54090f8b8385a9c75f172398977b5241ee8
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Nov 29 11:33:36 2019 +0100

    added some tests for expression parser and WIP for MFL and MFP
---
 build-utils/protocol-base-mspec/pom.xml            |  36 +++++
 .../mspec/parser/MessageFormatListener.java        |  16 +-
 .../language/mspec/parser/MessageFormatParser.java |  54 +++++--
 .../expression/ExpressionStringParserTest.java     | 178 +++++++++++++++++++++
 .../mspec/parser/MessageFormatListenerTest.java    | 162 +++++++++++++++++++
 .../mspec/parser/MessageFormatParserTest.java      |  88 ++++++++++
 6 files changed, 517 insertions(+), 17 deletions(-)

diff --git a/build-utils/protocol-base-mspec/pom.xml b/build-utils/protocol-base-mspec/pom.xml
index db361a8..a9096c2 100644
--- a/build-utils/protocol-base-mspec/pom.xml
+++ b/build-utils/protocol-base-mspec/pom.xml
@@ -64,6 +64,42 @@
       <groupId>org.antlr</groupId>
       <artifactId>antlr4-runtime</artifactId>
     </dependency>
+
+    <!-- Testing -->
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.vintage</groupId>
+      <artifactId>junit-vintage-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-junit-jupiter</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest-library</artifactId>
+    </dependency>
   </dependencies>
 
 </project>
\ No newline at end of file
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
index 74ff1cf..42c3ce3 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
@@ -55,6 +55,14 @@ public class MessageFormatListener extends MSpecBaseListener {
 
     private Map<String, TypeDefinition> types;
 
+    public Deque<List<Field>> getParserContexts() {
+        return parserContexts;
+    }
+
+    public Deque<List<EnumValue>> getEnumContexts() {
+        return enumContexts;
+    }
+
     public Map<String, TypeDefinition> getTypes() {
         return types;
     }
@@ -458,12 +466,4 @@ public class MessageFormatListener extends MSpecBaseListener {
         return quotedString;
     }
 
-    public static void main(String[] args) {
-        //Term term = new ExpressionStringParser().parse(IOUtils.toInputStream("CAST(CAST(parameter,S7ParameterUserData).items(hurz)[0],S7ParameterUserDataItemCPUFunctions).cpuFunctionType", Charset.defaultCharset()));
-        //Term term = new ExpressionStringParser().parse(IOUtils.toInputStream("CAST(parameter,S7ParameterUserData).items(hurz)[0]", Charset.defaultCharset()));
-        Term term = new ExpressionStringParser().parse(IOUtils.toInputStream("payload.lengthInBytes+4", Charset.defaultCharset()));
-
-        System.out.println(term);
-    }
-
 }
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParser.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParser.java
index bdd99fb..a134666 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParser.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParser.java
@@ -19,6 +19,7 @@
 
 package org.apache.plc4x.plugins.codegenerator.language.mspec.parser;
 
+import org.antlr.v4.runtime.CharStream;
 import org.antlr.v4.runtime.CharStreams;
 import org.antlr.v4.runtime.CommonTokenStream;
 import org.antlr.v4.runtime.tree.ParseTree;
@@ -27,24 +28,59 @@ import org.apache.plc4x.plugins.codegenerator.language.mspec.MSpecLexer;
 import org.apache.plc4x.plugins.codegenerator.language.mspec.MSpecParser;
 import org.apache.plc4x.plugins.codegenerator.types.definitions.TypeDefinition;
 
+import java.io.IOException;
 import java.io.InputStream;
 import java.util.Map;
+import java.util.function.Function;
+import java.util.function.Supplier;
 
 public class MessageFormatParser {
 
+    // TODO: can be used a instance once thread safety is asserted
+    private Function<CharStream, MSpecLexer> lexerBuilder;
+
+    // TODO: can be used a instance once thread safety is asserted
+    private Function<MSpecLexer, CommonTokenStream> commonTokenStreamBuilder;
+
+    // TODO: can be used a instance once thread safety is asserted
+    private Function<CommonTokenStream, MSpecParser> commonTokenStreamMSpecParserBuilder;
+
+    // TODO: can be used a instance once thread safety is asserted
+    private Supplier<ParseTreeWalker> voidParseTreeWalkerBuilder;
+
+    // TODO: can be used a instance once thread safety is asserted
+    private Supplier<MessageFormatListener> messageFormatListenerBuilder;
+
+    public MessageFormatParser() {
+        lexerBuilder = MSpecLexer::new;
+        commonTokenStreamBuilder = CommonTokenStream::new;
+        commonTokenStreamMSpecParserBuilder = MSpecParser::new;
+        voidParseTreeWalkerBuilder = ParseTreeWalker::new;
+        messageFormatListenerBuilder = MessageFormatListener::new;
+    }
+
+    MessageFormatParser(Function<CharStream, MSpecLexer> lexerBuilder, Function<MSpecLexer, CommonTokenStream> commonTokenStreamBuilder, Function<CommonTokenStream, MSpecParser> commonTokenStreamMSpecParserBuilder, Supplier<ParseTreeWalker> voidParseTreeWalkerBuilder, Supplier<MessageFormatListener> messageFormatListenerBuilder) {
+        this.lexerBuilder = lexerBuilder;
+        this.commonTokenStreamBuilder = commonTokenStreamBuilder;
+        this.commonTokenStreamMSpecParserBuilder = commonTokenStreamMSpecParserBuilder;
+        this.voidParseTreeWalkerBuilder = voidParseTreeWalkerBuilder;
+        this.messageFormatListenerBuilder = messageFormatListenerBuilder;
+    }
+
     public Map<String, TypeDefinition> parse(InputStream source) {
+        MSpecLexer lexer;
         try {
-            MSpecLexer lexer = new MSpecLexer(CharStreams.fromStream(source));
-            CommonTokenStream tokens = new CommonTokenStream(lexer);
-            MSpecParser parser = new MSpecParser(tokens);
-            ParseTree tree = parser.file();
-            ParseTreeWalker walker = new ParseTreeWalker();
-            MessageFormatListener listener = new MessageFormatListener();
-            walker.walk(listener, tree);
-            return listener.getTypes();
-        } catch (Exception e) {
+            lexer = lexerBuilder.apply(CharStreams.fromStream(source));
+        } catch (IOException e) {
             throw new RuntimeException(e);
         }
+        CommonTokenStream tokens = commonTokenStreamBuilder.apply(lexer);
+        MSpecParser parser = commonTokenStreamMSpecParserBuilder.apply(tokens);
+        ParseTree tree = parser.file();
+        ParseTreeWalker walker = voidParseTreeWalkerBuilder.get();
+        MessageFormatListener listener = messageFormatListenerBuilder.get();
+        walker.walk(listener, tree);
+        return listener.getTypes();
     }
 
 }
diff --git a/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParserTest.java b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParserTest.java
new file mode 100644
index 0000000..71c0222
--- /dev/null
+++ b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParserTest.java
@@ -0,0 +1,178 @@
+/*
+ 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.
+ */
+
+package org.apache.plc4x.plugins.codegenerator.language.mspec.expression;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.plc4x.plugins.codegenerator.types.terms.BinaryTerm;
+import org.apache.plc4x.plugins.codegenerator.types.terms.NumericLiteral;
+import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
+import org.apache.plc4x.plugins.codegenerator.types.terms.VariableLiteral;
+import org.junit.jupiter.api.Test;
+
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.function.Consumer;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.*;
+
+class ExpressionStringParserTest {
+
+    ExpressionStringParser SUT = new ExpressionStringParser();
+
+    @Test
+    void parseSimple() {
+        Term term = SUT.parse(IOUtils.toInputStream("payload.lengthInBytes+4", Charset.defaultCharset()));
+        assertThat(term, not(nullValue()));
+        assertThat(term, instanceOf(BinaryTerm.class));
+        BinaryTerm binaryTerm = (BinaryTerm) term;
+        assertVariableLiteral(
+            binaryTerm.getA(),
+            "payload",
+            null,
+            lengthInBytesVariableLiteral -> assertVariableLiteral(
+                lengthInBytesVariableLiteral,
+                "lengthInBytes"
+            )
+        );
+        assertNumericLiteral(binaryTerm.getB(), 4L);
+        assertThat(binaryTerm.getOperation(), is("+"));
+    }
+
+
+    @Test
+    void parseDoubleCast() {
+        Term term = SUT.parse(IOUtils.toInputStream("CAST(CAST(parameter,S7ParameterUserData).items(hurz)[0],S7ParameterUserDataItemCPUFunctions).cpuFunctionType", Charset.defaultCharset()));
+        assertVariableLiteral(
+            term,
+            "CAST",
+            outerCast -> {
+                assertThat(outerCast, hasSize(2));
+                assertVariableLiteral(
+                    outerCast.get(0),
+                    "CAST",
+                    innerCast -> {
+                        assertThat(innerCast, hasSize(2));
+                        assertVariableLiteral(
+                            innerCast.get(0),
+                            "parameter"
+                        );
+                        assertVariableLiteral(
+                            innerCast.get(1),
+                            "S7ParameterUserData"
+                        );
+                    },
+                    items -> {
+                        assertVariableLiteral(
+                            items,
+                            "items",
+                            hurzes -> {
+                                assertThat(hurzes, hasSize(1));
+                                assertVariableLiteral(
+                                    hurzes.get(0),
+                                    "hurz"
+                                );
+                            },
+                            null,
+                            0
+                        );
+                    });
+                assertVariableLiteral(
+                    outerCast.get(1),
+                    "S7ParameterUserDataItemCPUFunctions"
+                );
+            }, variableLiteral -> {
+                assertVariableLiteral(
+                    variableLiteral,
+                    "cpuFunctionType"
+                );
+            }
+        );
+    }
+
+    @Test
+    void parseCast() {
+        Term term = SUT.parse(IOUtils.toInputStream("CAST(parameter,S7ParameterUserData).items(hurz)[0]", Charset.defaultCharset()));
+        assertVariableLiteral(
+            term,
+            "CAST",
+            terms -> {
+                assertThat(terms, hasSize(2));
+                assertVariableLiteral(
+                    terms.get(0),
+                    "parameter"
+                );
+                assertVariableLiteral(
+                    terms.get(1),
+                    "S7ParameterUserData"
+                );
+            }, variableLiteral -> {
+                assertVariableLiteral(
+                    variableLiteral,
+                    "items",
+                    terms -> {
+                        assertThat(terms, hasSize(1));
+                        assertVariableLiteral(
+                            terms.get(0),
+                            "hurz"
+                        );
+                    },
+                    null,
+                    0
+                );
+            }
+        );
+    }
+
+    void assertNumericLiteral(Term term, Number number) {
+        assertThat(term, not(nullValue()));
+        assertThat(term, instanceOf(NumericLiteral.class));
+        NumericLiteral numericLiteral = (NumericLiteral) term;
+        assertThat(numericLiteral.getNumber(), is(number));
+    }
+
+    void assertVariableLiteral(Term term, String name) {
+        assertVariableLiteral(term, name, null, null, -1);
+    }
+
+    void assertVariableLiteral(Term term, String name, Consumer<List<Term>> argsAsserter, Consumer<VariableLiteral> childAsserter) {
+        assertVariableLiteral(term, name, argsAsserter, childAsserter, -1);
+    }
+
+    void assertVariableLiteral(Term term, String name, Consumer<List<Term>> argsAsserter, Consumer<VariableLiteral> childAsserter, int index) {
+        assertThat(term, not(nullValue()));
+        assertThat(term, instanceOf(VariableLiteral.class));
+        VariableLiteral variableLiteral = (VariableLiteral) term;
+        assertThat(variableLiteral.getName(), is(name));
+        assertThat(variableLiteral.getIndex(), is(index));
+        if (argsAsserter != null) {
+            argsAsserter.accept(variableLiteral.getArgs());
+        } else {
+            assertThat(variableLiteral.getArgs(), nullValue());
+        }
+        if (childAsserter != null) {
+            childAsserter.accept(variableLiteral.getChild());
+        } else {
+            assertThat(variableLiteral.getChild(), nullValue());
+        }
+    }
+
+
+}
\ No newline at end of file
diff --git a/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListenerTest.java b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListenerTest.java
new file mode 100644
index 0000000..3d9f4c4
--- /dev/null
+++ b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListenerTest.java
@@ -0,0 +1,162 @@
+/*
+ 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.
+ */
+
+package org.apache.plc4x.plugins.codegenerator.language.mspec.parser;
+
+import org.antlr.v4.runtime.CommonToken;
+import org.apache.plc4x.plugins.codegenerator.language.mspec.MSpecParser;
+import org.apache.plc4x.plugins.codegenerator.types.definitions.TypeDefinition;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.Map;
+
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+
+// TODO: implement me
+@ExtendWith(MockitoExtension.class)
+class MessageFormatListenerTest {
+
+    MessageFormatListener SUT;
+
+    @BeforeEach
+    void setUp() {
+        SUT = new MessageFormatListener();
+    }
+
+    @Test
+    void getTypes() {
+        Map<String, TypeDefinition> types = SUT.getTypes();
+        assertThat(types, nullValue());
+    }
+
+    @Test
+    void enterFile() {
+        assertThat(SUT.getParserContexts(), nullValue());
+        assertThat(SUT.getEnumContexts(), nullValue());
+        assertThat(SUT.getTypes(), nullValue());
+        SUT.enterFile(null);
+        assertThat(SUT.getParserContexts(), not(nullValue()));
+        assertThat(SUT.getEnumContexts(), not(nullValue()));
+        assertThat(SUT.getTypes(), not(nullValue()));
+    }
+
+    @Test
+    void enterComplexType() {
+        assertThat(SUT.getParserContexts(), nullValue());
+        assertThat(SUT.getEnumContexts(), nullValue());
+        assertThat(SUT.getTypes(), nullValue());
+        SUT.enterFile(null);
+        MSpecParser.ComplexTypeContext complexTypeContext = new MSpecParser.ComplexTypeContext(null, 0);
+        SUT.enterComplexType(complexTypeContext);
+        assertThat(SUT.getParserContexts(), hasSize(1));
+        assertThat(SUT.getEnumContexts(), hasSize(0));
+        assertThat(SUT.getTypes().values(), hasSize(0));
+        complexTypeContext.enumValues = new MSpecParser.EnumValueDefinitionContext(null, 0);
+        SUT.enterComplexType(complexTypeContext);
+        assertThat(SUT.getParserContexts(), hasSize(1));
+        assertThat(SUT.getEnumContexts(), hasSize(1));
+        assertThat(SUT.getTypes().values(), hasSize(0));
+    }
+
+    @Test
+    void exitComplexType() {
+        MSpecParser.ComplexTypeContext complexTypeContext = new MSpecParser.ComplexTypeContext(null, 0);
+        complexTypeContext.name = new MSpecParser.IdExpressionContext(null, 0);
+        complexTypeContext.name.id = new CommonToken(0);
+        SUT.exitComplexType(complexTypeContext);
+    }
+
+    @Test
+    void enterArrayField() {
+    }
+
+    @Test
+    void enterChecksumField() {
+    }
+
+    @Test
+    void enterConstField() {
+    }
+
+    @Test
+    void enterDiscriminatorField() {
+    }
+
+    @Test
+    void enterEnumField() {
+    }
+
+    @Test
+    void enterImplicitField() {
+    }
+
+    @Test
+    void enterManualArrayField() {
+    }
+
+    @Test
+    void enterManualField() {
+    }
+
+    @Test
+    void enterOptionalField() {
+    }
+
+    @Test
+    void enterPaddingField() {
+    }
+
+    @Test
+    void enterReservedField() {
+    }
+
+    @Test
+    void enterSimpleField() {
+    }
+
+    @Test
+    void enterTypeSwitchField() {
+    }
+
+    @Test
+    void enterVirtualField() {
+    }
+
+    @Test
+    void enterCaseStatement() {
+    }
+
+    @Test
+    void exitCaseStatement() {
+    }
+
+    @Test
+    void enterEnumValueDefinition() {
+    }
+
+    @Test
+    void main() {
+    }
+}
\ No newline at end of file
diff --git a/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParserTest.java b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParserTest.java
new file mode 100644
index 0000000..7aa47d2
--- /dev/null
+++ b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParserTest.java
@@ -0,0 +1,88 @@
+/*
+ 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.
+ */
+
+package org.apache.plc4x.plugins.codegenerator.language.mspec.parser;
+
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.tree.ParseTreeWalker;
+import org.apache.commons.io.IOUtils;
+import org.apache.plc4x.plugins.codegenerator.language.mspec.MSpecLexer;
+import org.apache.plc4x.plugins.codegenerator.language.mspec.MSpecParser;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
+
+// TODO: implement me
+@ExtendWith(MockitoExtension.class)
+class MessageFormatParserTest {
+
+    //@InjectMocks
+    MessageFormatParser SUT;
+
+    @Mock
+    MSpecLexer mSpecLexer;
+
+    @Mock
+    CommonTokenStream commonTokenStream;
+
+    @Mock
+    MSpecParser mSpecParser;
+
+    @Mock
+    ParseTreeWalker parseTreeWalker;
+
+    @Mock
+    MessageFormatListener messageFormatListener;
+
+    @BeforeEach
+    void setUp() {
+        SUT = new MessageFormatParser(
+            (_ignore) -> mSpecLexer,
+            (_ignore) -> commonTokenStream,
+            (_ignore) -> mSpecParser,
+            () -> parseTreeWalker,
+            () -> messageFormatListener
+        );
+    }
+
+    @Test
+    void parseNull() {
+        assertThrows(NullPointerException.class, () -> SUT.parse(null));
+    }
+
+    @Disabled("mockito broken because of NPE in REAL code")
+    @Test
+    void parseSomething() {
+        // TODO: seems like mockito is broken somehow...
+        MSpecParser mSpecParser = mock(MSpecParser.class);
+        // TODO: ... because this throws a NPE... (somehow call ends up in real code)
+        mSpecParser.file();
+        InputStream is = IOUtils.toInputStream("test", StandardCharsets.UTF_8);
+        SUT.parse(is);
+    }
+}
\ No newline at end of file


[plc4x] 05/07: added test for parent expression

Posted by sr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch feature/ams_ads_mpsec
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 836638fc8b9f7baa80ae091f534d46108876eb78
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Thu Dec 5 11:49:27 2019 +0100

    added test for parent expression
---
 .../expression/ExpressionStringParserTest.java     | 23 ++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParserTest.java b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParserTest.java
index 606885b..a89065f 100644
--- a/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParserTest.java
+++ b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParserTest.java
@@ -20,10 +20,7 @@
 package org.apache.plc4x.plugins.codegenerator.language.mspec.expression;
 
 import org.apache.commons.io.IOUtils;
-import org.apache.plc4x.plugins.codegenerator.types.terms.BinaryTerm;
-import org.apache.plc4x.plugins.codegenerator.types.terms.NumericLiteral;
-import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
-import org.apache.plc4x.plugins.codegenerator.types.terms.VariableLiteral;
+import org.apache.plc4x.plugins.codegenerator.types.terms.*;
 import org.junit.jupiter.api.Test;
 
 import java.nio.charset.Charset;
@@ -98,7 +95,8 @@ class ExpressionStringParserTest {
                     outerCast.get(1),
                     "S7ParameterUserDataItemCPUFunctions"
                 );
-            }, variableLiteral -> {
+            },
+            variableLiteral -> {
                 assertVariableLiteral(
                     variableLiteral,
                     "cpuFunctionType"
@@ -123,7 +121,8 @@ class ExpressionStringParserTest {
                     terms.get(1),
                     "S7ParameterUserData"
                 );
-            }, variableLiteral -> {
+            },
+            variableLiteral -> {
                 assertVariableLiteral(
                     variableLiteral,
                     "items",
@@ -145,6 +144,18 @@ class ExpressionStringParserTest {
     void testParentReference() {
         Term term = SUT.parse(IOUtils.toInputStream("../data.lengthInBytes", Charset.defaultCharset()));
         assertThat(term, not(nullValue()));
+        assertThat(term, instanceOf(UnaryTerm.class));
+        UnaryTerm unaryTerm = (UnaryTerm) term;
+        assertThat(unaryTerm.getOperation(), is(".."));
+        assertVariableLiteral(
+            unaryTerm.getA(),
+            "data",
+            null,
+            variableLiteral -> assertVariableLiteral(
+                variableLiteral,
+                "lengthInBytes"
+            )
+        );
     }
 
     void assertNumericLiteral(Term term, Number number) {


[plc4x] 06/07: added bitmask and possibility to add comments at more places

Posted by sr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch feature/ams_ads_mpsec
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 94907da6d220a9e67107ddacbfb9d1908322085d
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Dec 6 11:11:24 2019 +0100

    added bitmask and possibility to add comments at more places
---
 .../plugins/codegenerator/language/mspec/MSpec.g4  | 16 ++++++++++++-
 .../src/test/resources/mspec.example               | 27 +++++++++++-----------
 pom.xml                                            |  2 +-
 3 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4 b/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4
index 8d058ca..b37751c 100644
--- a/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4
+++ b/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4
@@ -31,11 +31,13 @@ complexType
  : 'type' name=idExpression (LBRACKET params=argumentList RBRACKET)? fieldDefinition+
  | 'discriminatedType' name=idExpression (LBRACKET params=argumentList RBRACKET)? fieldDefinition+
  | 'enum' type=typeReference name=idExpression (LBRACKET params=argumentList RBRACKET)? enumValues=enumValueDefinition+
+ | 'bitmask' type=typeReference name=idExpression (LBRACKET params=argumentList RBRACKET)? bitmaskValues=bitmaskValueDefinition+
  ;
 
 
 fieldDefinition
  : LBRACKET field (LBRACKET params=multipleExpressions RBRACKET)? RBRACKET
+ | COMMENT
  ;
 
 field
@@ -44,6 +46,7 @@ field
  | constField
  | discriminatorField
  | enumField
+ | bitmaskField
  | implicitField
  | manualArrayField
  | manualField
@@ -75,6 +78,10 @@ enumField
  : 'enum' type=typeReference name=idExpression
  ;
 
+bitmaskField
+ : 'bitmask' type=typeReference name=idExpression
+ ;
+
 implicitField
  : 'implicit' type=dataType name=idExpression serializationExpression=expression
  ;
@@ -113,8 +120,13 @@ virtualField
 
 enumValueDefinition
  : LBRACKET valueExpression=expression name=IDENTIFIER (LBRACKET constantValueExpressions=multipleExpressions RBRACKET)? RBRACKET
+ | COMMENT
  ;
 
+bitmaskValueDefinition
+ : LBRACKET valueExpression=expression name=IDENTIFIER (LBRACKET constantValueExpressions=multipleExpressions RBRACKET)? RBRACKET
+ | COMMENT
+ ;
 
 typeReference
  : complexTypeReference=IDENTIFIER
@@ -127,6 +139,7 @@ caseStatement
 
 dataType
  : base='bit'
+ | base='byte' size=INTEGER_LITERAL
  | base='int' size=INTEGER_LITERAL
  | base='uint' size=INTEGER_LITERAL
  | base='float' size=INTEGER_LITERAL
@@ -161,6 +174,7 @@ innerExpression
  | '(' innerExpression ')'
  | '"' innerExpression '"'
  | '!' innerExpression
+ | '../' innerExpression
  ;
 
 COMMENT
@@ -226,4 +240,4 @@ IDENTIFIER
  ;
 
 WS  :  [ \t\r\n\u000C]+ -> skip
-;
\ No newline at end of file
+;
diff --git a/build-utils/protocol-base-mspec/src/test/resources/mspec.example b/build-utils/protocol-base-mspec/src/test/resources/mspec.example
index 963b5d9..51bed3d 100644
--- a/build-utils/protocol-base-mspec/src/test/resources/mspec.example
+++ b/build-utils/protocol-base-mspec/src/test/resources/mspec.example
@@ -22,22 +22,23 @@
 ////////////////////////////////////////////////////////////////
 
 [type 'AMSPacket'
-    [reserved   uint       16       '0x0000'                                             ]
-    [implicit   uint       32       'length' 'header.lengthInBytes + data.lengthInBytes' ]
-    [simple     AMSHeader  'header'                                                      ]
-    [simple     ADSData    'data'                                                        ]
+    [reserved   uint       16       '0x0000'                                                   ]
+    [implicit   uint       32       'packetLength' 'header.lengthInBytes + data.lengthInBytes' ]
+    [simple     AMSHeader  'header'                                                            ]
+    [simple     ADSData    'data'                                                              ]
 ]
 
 [type 'AMSHeader'
-    [simple     AMSNetId        'targetAmsNetId'        ]
-    [simple     uint        16  'targetAmsPort'         ]
-    [simple     AMSNetId        'sourceAmsNetId'        ]
-    [simple     uint        16  'sourceAmsPort'         ]
-    [enum       CommandId       'commandId'             ]
-    [bitmask    State           'state'                 ]
-    [simple     uint        32  '../data.lengthInBytes' ]
-    [simple     uint        32  'errorCode'             ]
-    [simple     byte        32  'invokeId'              ]
+    [simple     AMSNetId        'targetAmsNetId'                            ]
+    [simple     uint        16  'targetAmsPort'                             ]
+    [simple     AMSNetId        'sourceAmsNetId'                            ]
+    [simple     uint        16  'sourceAmsPort'                             ]
+    [enum       CommandId       'commandId'                                 ]
+    [bitmask    State           'state'                                     ]
+    [implicit   uint        32  'dataLength'        '../data.lengthInBytes' ]
+    [simple     uint        32  'errorCode'                                 ]
+    // free usable field of 4 bytes
+    [simple     byte        32  'invokeId'                                  ]
 ]
 
 [enum uint 16 'CommandId'
diff --git a/pom.xml b/pom.xml
index efb7a2e..46f76f9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -103,7 +103,7 @@
     <!-- Exclude all generated code -->
     <sonar.exclusions>**/generated-sources</sonar.exclusions>
 
-    <plc4x-code-generation.version>1.0.0</plc4x-code-generation.version>
+    <plc4x-code-generation.version>1.1.0-SNAPSHOT</plc4x-code-generation.version>
 
     <antlr.version>4.7.2</antlr.version>
     <asm.version>5.0.4</asm.version>


[plc4x] 04/07: added parent expressionn

Posted by sr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch feature/ams_ads_mpsec
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit f3c6f86d505698ce27872678c21a463ec5668871
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Thu Dec 5 10:01:09 2019 +0100

    added parent expressionn
---
 .../language/mspec/expression/Expression.g4        |  1 +
 .../mspec/expression/ExpressionStringListener.java | 11 ++++++++
 .../expression/ExpressionStringParserTest.java     |  6 +++++
 .../mspec/parser/MessageFormatParserTest.java      | 11 +++-----
 .../src/test/resources/mspec.example               | 29 +++++++++++-----------
 .../main/resources/protocols/amsads/amsads.mspec   | 26 +++++++++----------
 6 files changed, 50 insertions(+), 34 deletions(-)

diff --git a/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/Expression.g4 b/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/Expression.g4
index 7e8c288..fcda12a 100644
--- a/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/Expression.g4
+++ b/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/Expression.g4
@@ -52,6 +52,7 @@ expression
  | identifierSegment                                    #identifierExpression
  | String indexes?                                      #stringExpression
  | '(' expression ')' indexes?                          #expressionExpression
+ | '../' expression                                     #parentExpression
  ;
 
 identifierSegment
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringListener.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringListener.java
index f4ae9e3..eb72be7 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringListener.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringListener.java
@@ -187,6 +187,17 @@ public class ExpressionStringListener extends ExpressionBaseListener {
         parserContexts.peek().add(ut);
     }
 
+    @Override
+    public void enterParentExpression(ExpressionParser.ParentExpressionContext ctx) {
+        parserContexts.push(new LinkedList<>());
+    }
+
+    @Override
+    public void exitParentExpression(ExpressionParser.ParentExpressionContext ctx) {
+        UnaryTerm ut = getUnaryTerm("..", parserContexts.pop());
+        parserContexts.peek().add(ut);
+    }
+
     /////////////////////////////////////////////////////////////////////////////////////////
     // Binary Terms
     /////////////////////////////////////////////////////////////////////////////////////////
diff --git a/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParserTest.java b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParserTest.java
index 71c0222..606885b 100644
--- a/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParserTest.java
+++ b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParserTest.java
@@ -141,6 +141,12 @@ class ExpressionStringParserTest {
         );
     }
 
+    @Test
+    void testParentReference() {
+        Term term = SUT.parse(IOUtils.toInputStream("../data.lengthInBytes", Charset.defaultCharset()));
+        assertThat(term, not(nullValue()));
+    }
+
     void assertNumericLiteral(Term term, Number number) {
         assertThat(term, not(nullValue()));
         assertThat(term, instanceOf(NumericLiteral.class));
diff --git a/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParserTest.java b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParserTest.java
index 37b9720..127a2d2 100644
--- a/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParserTest.java
+++ b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParserTest.java
@@ -19,12 +19,10 @@
 
 package org.apache.plc4x.plugins.codegenerator.language.mspec.parser;
 
-import org.apache.commons.io.IOUtils;
-import org.junit.jupiter.api.Disabled;
+import org.apache.plc4x.plugins.codegenerator.types.definitions.TypeDefinition;
 import org.junit.jupiter.api.Test;
 
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
+import java.util.Map;
 
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
@@ -37,10 +35,9 @@ class MessageFormatParserTest {
         assertThrows(NullPointerException.class, () -> SUT.parse(null));
     }
 
-    @Disabled("mockito broken because of NPE in REAL code")
     @Test
     void parseSomething() {
-        InputStream is = IOUtils.toInputStream("test", StandardCharsets.UTF_8);
-        SUT.parse(is);
+        Map<String, TypeDefinition> parse = SUT.parse(getClass().getResourceAsStream("/mspec.example"));
+        System.out.println(parse);
     }
 }
\ No newline at end of file
diff --git a/protocols/amsads/src/main/resources/protocols/amsads/amsads.mspec b/build-utils/protocol-base-mspec/src/test/resources/mspec.example
similarity index 73%
copy from protocols/amsads/src/main/resources/protocols/amsads/amsads.mspec
copy to build-utils/protocol-base-mspec/src/test/resources/mspec.example
index 0cc973f..963b5d9 100644
--- a/protocols/amsads/src/main/resources/protocols/amsads/amsads.mspec
+++ b/build-utils/protocol-base-mspec/src/test/resources/mspec.example
@@ -22,22 +22,22 @@
 ////////////////////////////////////////////////////////////////
 
 [type 'AMSPacket'
-    [reserved   uint       16   '0x0000'                                      ]
-    [implicit   uint       32   'header.lengthInBytes + data.lengthInBytes'   ]
-    [simple     AMSHeader  'header'                                           ]
-    [simple     ADSData    'data'                                             ]
+    [reserved   uint       16       '0x0000'                                             ]
+    [implicit   uint       32       'length' 'header.lengthInBytes + data.lengthInBytes' ]
+    [simple     AMSHeader  'header'                                                      ]
+    [simple     ADSData    'data'                                                        ]
 ]
 
 [type 'AMSHeader'
-    [simple     AMSNetId        'targetAmsNetId'    ]
-    [simple     uint        16  'targetAmsPort'     ]
-    [simple     AMSNetId        'sourceAmsNetId'    ]
-    [simple     uint        16  'sourceAmsPort'     ]
-    [enum       CommandId       'commandId'         ]
-    [bitmask    State           'state'             ]
-    [simple     uint        32  '../data.lengthInBytes'        ]
-    [simple     uint        32  'errorCode']
-    [simple     byte        32  'invokeId'          ]
+    [simple     AMSNetId        'targetAmsNetId'        ]
+    [simple     uint        16  'targetAmsPort'         ]
+    [simple     AMSNetId        'sourceAmsNetId'        ]
+    [simple     uint        16  'sourceAmsPort'         ]
+    [enum       CommandId       'commandId'             ]
+    [bitmask    State           'state'                 ]
+    [simple     uint        32  '../data.lengthInBytes' ]
+    [simple     uint        32  'errorCode'             ]
+    [simple     byte        32  'invokeId'              ]
 ]
 
 [enum uint 16 'CommandId'
@@ -76,5 +76,6 @@
 
 [type 'ADSData'
    // TODO: implement me..... arrrrrrrggggggggggggg
-   ....
+   //....
+   [simple     uint        8   'random'            ]
 ]
\ No newline at end of file
diff --git a/protocols/amsads/src/main/resources/protocols/amsads/amsads.mspec b/protocols/amsads/src/main/resources/protocols/amsads/amsads.mspec
index 0cc973f..8f22167 100644
--- a/protocols/amsads/src/main/resources/protocols/amsads/amsads.mspec
+++ b/protocols/amsads/src/main/resources/protocols/amsads/amsads.mspec
@@ -22,22 +22,22 @@
 ////////////////////////////////////////////////////////////////
 
 [type 'AMSPacket'
-    [reserved   uint       16   '0x0000'                                      ]
-    [implicit   uint       32   'header.lengthInBytes + data.lengthInBytes'   ]
-    [simple     AMSHeader  'header'                                           ]
-    [simple     ADSData    'data'                                             ]
+    [reserved   uint       16       '0x0000'                                             ]
+    [implicit   uint       32       'length' 'header.lengthInBytes + data.lengthInBytes' ]
+    [simple     AMSHeader  'header'                                                      ]
+    [simple     ADSData    'data'                                                        ]
 ]
 
 [type 'AMSHeader'
-    [simple     AMSNetId        'targetAmsNetId'    ]
-    [simple     uint        16  'targetAmsPort'     ]
-    [simple     AMSNetId        'sourceAmsNetId'    ]
-    [simple     uint        16  'sourceAmsPort'     ]
-    [enum       CommandId       'commandId'         ]
-    [bitmask    State           'state'             ]
-    [simple     uint        32  '../data.lengthInBytes'        ]
-    [simple     uint        32  'errorCode']
-    [simple     byte        32  'invokeId'          ]
+    [simple     AMSNetId        'targetAmsNetId'        ]
+    [simple     uint        16  'targetAmsPort'         ]
+    [simple     AMSNetId        'sourceAmsNetId'        ]
+    [simple     uint        16  'sourceAmsPort'         ]
+    [enum       CommandId       'commandId'             ]
+    [bitmask    State           'state'                 ]
+    [simple     uint        32  '../data.lengthInBytes' ]
+    [simple     uint        32  'errorCode'             ]
+    [simple     byte        32  'invokeId'              ]
 ]
 
 [enum uint 16 'CommandId'


[plc4x] 01/07: initial ams/ads mspec

Posted by sr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch feature/ams_ads_mpsec
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit e40253f4c16bcd76fe18fbe5a0bc61edc6f4e3a8
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Thu Nov 28 12:02:54 2019 +0100

    initial ams/ads mspec
---
 protocols/amsads/pom.xml                           |  43 ++++
 .../plc4x/protocol/amsads/AMSADSProtocol.java      |  47 ++++
 ...e.plc4x.plugins.codegenerator.protocol.Protocol |  38 ++++
 .../main/resources/protocols/amsads/amsads.mspec   |  80 +++++++
 protocols/pom.xml                                  |   1 +
 sandbox/pom.xml                                    |   1 +
 sandbox/test-java-amsads-driver/README.adoc        |  35 +++
 sandbox/test-java-amsads-driver/pom.xml            | 171 +++++++++++++++
 .../apache/plc4x/java/amsads/AMSADSPlcDriver.java  |  74 +++++++
 .../org/apache/plc4x/java/amsads/Df1Field.java     |  62 ++++++
 .../amsads/connection/BaseAMSADSConnection.java    |  34 +++
 .../amsads/connection/SerialAMSADSConnection.java  | 148 +++++++++++++
 .../apache/plc4x/java/amsads/fields/DataType.java  |  44 ++++
 .../plc4x/java/amsads/protocol/AMSADSProtocol.java | 157 ++++++++++++++
 .../java/amsads/protocol/Plc4XDf1Protocol.java     | 172 +++++++++++++++
 .../apache/plc4x/java/amsads/util/DF1Utils.java    | 158 ++++++++++++++
 .../plc4x/java/amsads/util/Df1FieldHandler.java    |  39 ++++
 .../services/org.apache.plc4x.java.spi.PlcDriver   |  38 ++++
 .../plc4x/java/amsads/AMSADSPlcDriverTest.java     |  44 ++++
 .../protocol/amsads/BenchmarkGeneratedDf1.java     |  81 +++++++
 .../plc4x/protocol/amsads/BenchmarkManualDf1.java  | 239 +++++++++++++++++++++
 .../org/apache/plc4x/protocol/amsads/Df1Test.java  |  30 +++
 .../apache/plc4x/protocol/amsads/EndToEndTest.java |  56 +++++
 .../org/apache/plc4x/protocol/amsads/IOTest.java   |  99 +++++++++
 .../src/test/resources/testsuite/Df1Testsuite.xml  | 101 +++++++++
 25 files changed, 1992 insertions(+)

diff --git a/protocols/amsads/pom.xml b/protocols/amsads/pom.xml
new file mode 100644
index 0000000..f48b8b5
--- /dev/null
+++ b/protocols/amsads/pom.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.plc4x</groupId>
+    <artifactId>plc4x-protocols</artifactId>
+    <version>0.6.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>plc4x-protocols-amsads</artifactId>
+
+  <name>Protocols: AMS/ADS</name>
+  <description>Base protocol specifications for the AMS/ADS protocol</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4x-build-utils-protocol-base-mspec</artifactId>
+      <version>0.6.0-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/protocols/amsads/src/main/java/org/apache/plc4x/protocol/amsads/AMSADSProtocol.java b/protocols/amsads/src/main/java/org/apache/plc4x/protocol/amsads/AMSADSProtocol.java
new file mode 100644
index 0000000..0d872a6
--- /dev/null
+++ b/protocols/amsads/src/main/java/org/apache/plc4x/protocol/amsads/AMSADSProtocol.java
@@ -0,0 +1,47 @@
+/*
+ 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.
+ */
+
+package org.apache.plc4x.protocol.amsads;
+
+import org.apache.plc4x.plugins.codegenerator.language.mspec.parser.MessageFormatParser;
+import org.apache.plc4x.plugins.codegenerator.protocol.Protocol;
+import org.apache.plc4x.plugins.codegenerator.types.definitions.ComplexTypeDefinition;
+import org.apache.plc4x.plugins.codegenerator.types.definitions.TypeDefinition;
+import org.apache.plc4x.plugins.codegenerator.types.exceptions.GenerationException;
+
+import java.io.InputStream;
+import java.util.Map;
+
+public class AMSADSProtocol implements Protocol {
+
+    @Override
+    public String getName() {
+        return "amsads";
+    }
+
+    @Override
+    public Map<String, TypeDefinition> getTypeDefinitions() throws GenerationException {
+        InputStream schemaInputStream = AMSADSProtocol.class.getResourceAsStream("/protocols/amsads/amsads.mspec");
+        if(schemaInputStream == null) {
+            throw new GenerationException("Error loading message-format schema for protocol '" + getName() + "'");
+        }
+        return new MessageFormatParser().parse(schemaInputStream);
+    }
+
+}
diff --git a/protocols/amsads/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol b/protocols/amsads/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol
new file mode 100644
index 0000000..9d1f50e
--- /dev/null
+++ b/protocols/amsads/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol
@@ -0,0 +1,38 @@
+#
+# 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.
+#
+
+#
+# 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.
+#
+org.apache.plc4x.protocol.amsads.AMSADSProtocol
\ No newline at end of file
diff --git a/protocols/amsads/src/main/resources/protocols/amsads/amsads.mspec b/protocols/amsads/src/main/resources/protocols/amsads/amsads.mspec
new file mode 100644
index 0000000..0cc973f
--- /dev/null
+++ b/protocols/amsads/src/main/resources/protocols/amsads/amsads.mspec
@@ -0,0 +1,80 @@
+//
+// 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.
+//
+
+////////////////////////////////////////////////////////////////
+// AMS/TCP Paket
+////////////////////////////////////////////////////////////////
+
+[type 'AMSPacket'
+    [reserved   uint       16   '0x0000'                                      ]
+    [implicit   uint       32   'header.lengthInBytes + data.lengthInBytes'   ]
+    [simple     AMSHeader  'header'                                           ]
+    [simple     ADSData    'data'                                             ]
+]
+
+[type 'AMSHeader'
+    [simple     AMSNetId        'targetAmsNetId'    ]
+    [simple     uint        16  'targetAmsPort'     ]
+    [simple     AMSNetId        'sourceAmsNetId'    ]
+    [simple     uint        16  'sourceAmsPort'     ]
+    [enum       CommandId       'commandId'         ]
+    [bitmask    State           'state'             ]
+    [simple     uint        32  '../data.lengthInBytes'        ]
+    [simple     uint        32  'errorCode']
+    [simple     byte        32  'invokeId'          ]
+]
+
+[enum uint 16 'CommandId'
+    ['0x00' INVALID]
+    ['0x01' ADS_READ_DEVICE_INFO]
+    ['0x02' ADS_READ]
+    ['0x03' ADS_WRITE]
+    ['0x04' ADS_READ_STATE]
+    ['0x05' ADS_WRITE_CONTROL]
+    ['0x06' ADS_ADD_DEVICE_NOTIFICATION]
+    ['0x07' ADS_DELETE_DEVICE_NOTIFICATION]
+    ['0x08' ADS_DEVICE_NOTIFICATION]
+    ['0x09' ADS_READ_WRITE]
+]
+
+[bitmask byte 2 'State'
+    ['0b0000_0000_0000_0001' RESPONSE]
+    ['0b0000_0000_0000_0010' NO_RETURN]
+    ['0b0000_0000_0000_0100' ADS_COMMAND]
+    ['0b0000_0000_0000_1000' SYSTEM_COMMAND]
+    ['0b0000_0000_0001_0000' HIGH_PRIORITY_COMMAND]
+    ['0b0000_0000_0010_0000' TIMESTAMP_ADDED]
+    ['0b0000_0000_0100_0000' UDP_COMMAND]
+    ['0b0000_0000_1000_0000' INIT_COMMAND]
+    ['0b1000_0000_0000_0000' BROADCAST]
+]
+
+[type 'AMSNetId'
+    [simple     uint        8   'octet1'            ]
+    [simple     uint        8   'octet2'            ]
+    [simple     uint        8   'octet3'            ]
+    [simple     uint        8   'octet4'            ]
+    [simple     uint        8   'octet5'            ]
+    [simple     uint        8   'octet6'            ]
+]
+
+[type 'ADSData'
+   // TODO: implement me..... arrrrrrrggggggggggggg
+   ....
+]
\ No newline at end of file
diff --git a/protocols/pom.xml b/protocols/pom.xml
index 73d2874..5abb27e 100644
--- a/protocols/pom.xml
+++ b/protocols/pom.xml
@@ -190,6 +190,7 @@
   </build>
 
   <modules>
+    <module>amsads</module>
     <module>ab-eth</module>
     <module>bacnetip</module>
     <module>df1</module>
diff --git a/sandbox/pom.xml b/sandbox/pom.xml
index 600d99c..3173d2e 100644
--- a/sandbox/pom.xml
+++ b/sandbox/pom.xml
@@ -39,6 +39,7 @@
     <module>plc-simulator</module>
     <module>streampipes-connectors</module>
 
+    <module>test-java-amsads-driver</module>
     <module>test-java-bacnetip-driver</module>
     <module>test-java-knxnetip-driver</module>
     <module>test-java-s7-driver</module>
diff --git a/sandbox/test-java-amsads-driver/README.adoc b/sandbox/test-java-amsads-driver/README.adoc
new file mode 100644
index 0000000..4652b54
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/README.adoc
@@ -0,0 +1,35 @@
+//
+//  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.
+//
+
+== Using the Driver in the hello-world example
+
+Add the driver to the pom.xml
+
+        <dependency>
+          <groupId>org.apache.plc4x.sandbox</groupId>
+          <artifactId>test-java-amsads-driver</artifactId>
+          <version>0.6.0-SNAPSHOT</version>
+          <scope>runtime</scope>
+        </dependency>
+
+Then start the Hello world (Ideally in IntelliJ) with the following program arguments:
+
+    amsads:serial///{com-port-name} {address}
+
+Currently the parsing of addresses is not implemented yet, so it will not work.
+
+But as soon as that's done, this should work.
\ No newline at end of file
diff --git a/sandbox/test-java-amsads-driver/pom.xml b/sandbox/test-java-amsads-driver/pom.xml
new file mode 100644
index 0000000..f9efcf5
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/pom.xml
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.plc4x.sandbox</groupId>
+    <artifactId>plc4x-sandbox</artifactId>
+    <version>0.6.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>test-java-amsads-driver</artifactId>
+
+  <name>Sandbox: Test Generated AMS/ADS Driver</name>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.plc4x.plugins</groupId>
+        <artifactId>plc4x-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>test</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>generate-driver</goal>
+            </goals>
+            <configuration>
+              <protocolName>amsads</protocolName>
+              <languageName>java</languageName>
+              <outputFlavor>read-write</outputFlavor>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-api</artifactId>
+      <version>0.6.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-protocol-driver-base</artifactId>
+      <version>0.6.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-protocol-driver-base-tcp</artifactId>
+      <version>0.6.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-protocol-driver-base-serial</artifactId>
+      <version>0.6.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-utils-driver-base-java</artifactId>
+      <version>0.6.0-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-buffer</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-annotations</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4x-build-utils-language-java</artifactId>
+      <version>0.6.0-SNAPSHOT</version>
+      <!-- Scope is 'provided' as this way it's not shipped with the driver -->
+      <scope>provided</scope>
+    </dependency>
+
+  <!--  &lt;!&ndash; https://mvnrepository.com/artifact/org.rxtx/rxtx &ndash;&gt;
+    <dependency>
+      <groupId>org.rxtx</groupId>
+      <artifactId>rxtx</artifactId>
+      <version>2.1.7</version>
+    </dependency>-->
+
+    <dependency>
+      <groupId>com.github.purejavacomm</groupId>
+      <artifactId>purejavacomm</artifactId>
+      <version>1.0.2.RELEASE</version>
+    </dependency>
+
+    <!-- Logging -->
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>log4j-over-slf4j</artifactId>
+      <version>1.7.25</version>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4x-protocols-amsads</artifactId>
+      <version>0.6.0-SNAPSHOT</version>
+      <!-- Scope is 'provided' as this way it's not shipped with the driver -->
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-utils-protocol-test-utils</artifactId>
+      <version>0.6.0-SNAPSHOT</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.dataformat</groupId>
+      <artifactId>jackson-dataformat-xml</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-launcher</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+  </dependencies>
+
+</project>
diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/AMSADSPlcDriver.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/AMSADSPlcDriver.java
new file mode 100644
index 0000000..34b584f
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/AMSADSPlcDriver.java
@@ -0,0 +1,74 @@
+/*
+ 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.
+ */
+package org.apache.plc4x.java.amsads;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.authentication.PlcAuthentication;
+import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
+import org.apache.plc4x.java.df1.connection.SerialDf1Connection;
+import org.apache.plc4x.java.spi.PlcDriver;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class AMSADSPlcDriver implements PlcDriver {
+
+    // TODO there is only serial, I guess?
+    public static final Pattern INET_ADDRESS_PATTERN = Pattern.compile("tcp://(?<host>[\\w.]+)(:(?<port>\\d*))?");
+    public static final Pattern SERIAL_PATTERN = Pattern.compile("serial://(?<serialDefinition>/?[a-zA-Z0-9/]*)");
+    public static final Pattern DF1_URI_PATTERN = Pattern.compile("^df1:(" + INET_ADDRESS_PATTERN + "|" + SERIAL_PATTERN + ")/?" + "(?<params>\\?.*)?");
+
+    @Override
+    public String getProtocolCode() {
+        return "df1";
+    }
+
+    @Override
+    public String getProtocolName() {
+        return "Allen-Bradley DF1";
+    }
+
+    @Override
+    public PlcConnection connect(String url) throws PlcConnectionException {
+        Matcher matcher = DF1_URI_PATTERN.matcher(url);
+        if (!matcher.matches()) {
+            throw new PlcConnectionException(
+                "Connection url doesn't match the format 'df1:{type}//{port|host}'");
+        }
+
+        String host = matcher.group("host");
+        String serialDefinition = matcher.group("serialDefinition");
+        String portString = matcher.group("port");
+        Integer port = StringUtils.isNotBlank(portString) ? Integer.parseInt(portString) : null;
+        String params = matcher.group("params") != null ? matcher.group("params").substring(1) : null;
+
+        if (serialDefinition != null) {
+            return new SerialDf1Connection(serialDefinition, params);
+        } else {
+            throw new PlcConnectionException("TCP DF1 connections not implemented yet.");
+        }
+    }
+
+    @Override
+    public PlcConnection connect(String url, PlcAuthentication authentication) throws PlcConnectionException {
+        throw new PlcConnectionException("DF1 connections doesn't support authentication.");
+    }
+
+}
diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/Df1Field.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/Df1Field.java
new file mode 100644
index 0000000..762425a
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/Df1Field.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+package org.apache.plc4x.java.amsads;
+
+import com.sun.jna.StringArray;
+import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.df1.fields.DataType;
+
+public class Df1Field implements PlcField {
+
+    private final int address;
+    private final int size;
+    private final DataType dataType;
+    private final addressType address_type;
+
+    public Df1Field(int address, int size, DataType dataType, addressType address_type) {
+        this.address = address;
+        this.size = size;
+        this.dataType = dataType;
+        this.address_type = address_type;
+    }
+
+    public int getAddress() {
+        return address;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    public DataType getDataType() {
+        return dataType;
+    }
+
+    public addressType getAddress_type() { return address_type; }
+
+    public static PlcField of(String fieldQuery) {
+        String[] tmp = fieldQuery.split(":");
+        return new Df1Field(Integer.parseInt(tmp[0]), DataType.valueOf(tmp[1]).getLength(),DataType.valueOf(tmp[1]), addressType.OFFSET);
+    }
+
+    public enum addressType {
+        OFFSET,
+        LOGICAL
+    }
+}
diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/connection/BaseAMSADSConnection.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/connection/BaseAMSADSConnection.java
new file mode 100644
index 0000000..f1bdf79
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/connection/BaseAMSADSConnection.java
@@ -0,0 +1,34 @@
+/*
+ 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.
+ */
+package org.apache.plc4x.java.amsads.connection;
+
+import org.apache.plc4x.java.base.connection.ChannelFactory;
+import org.apache.plc4x.java.base.connection.NettyPlcConnection;
+
+public abstract class BaseAMSADSConnection extends NettyPlcConnection {
+
+    public BaseAMSADSConnection(ChannelFactory channelFactory) {
+        super(channelFactory);
+    }
+
+    public BaseAMSADSConnection(ChannelFactory channelFactory, boolean awaitSessionSetupComplete) {
+        super(channelFactory, awaitSessionSetupComplete);
+    }
+
+}
diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/connection/SerialAMSADSConnection.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/connection/SerialAMSADSConnection.java
new file mode 100644
index 0000000..4eded14
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/connection/SerialAMSADSConnection.java
@@ -0,0 +1,148 @@
+/*
+ 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.
+ */
+package org.apache.plc4x.java.amsads.connection;
+
+import io.netty.channel.*;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
+import org.apache.plc4x.java.api.messages.PlcWriteRequest;
+import org.apache.plc4x.java.api.messages.PlcWriteResponse;
+import org.apache.plc4x.java.base.connection.ChannelFactory;
+import org.apache.plc4x.java.base.connection.SerialChannelFactory;
+import org.apache.plc4x.java.base.events.ConnectedEvent;
+import org.apache.plc4x.java.base.messages.*;
+import org.apache.plc4x.java.df1.protocol.Df1Protocol;
+import org.apache.plc4x.java.df1.protocol.Plc4XDf1Protocol;
+import org.apache.plc4x.java.df1.util.Df1FieldHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.CompletableFuture;
+
+public class SerialAMSADSConnection extends BaseAMSADSConnection implements PlcReader, PlcWriter {
+
+    private static final Logger logger = LoggerFactory.getLogger(SerialAMSADSConnection.class);
+
+    private short localAddr;
+    private short remoteAddr;
+
+    public SerialAMSADSConnection(String comPortName, String params) {
+        this(new SerialChannelFactory(comPortName), params);
+    }
+
+    public SerialAMSADSConnection(ChannelFactory channelFactory, String params) {
+        super(channelFactory, false);
+        this.localAddr = (short) 0x00;
+        this.remoteAddr = (short) 0x09;
+
+        // Override some of the settings, if they are asked for.
+        if (!StringUtils.isEmpty(params)) {
+            for (String param : params.split("&")) {
+                String[] paramElements = param.split("=");
+                String paramName = paramElements[0];
+                if (paramElements.length == 2) {
+                    String paramValue = paramElements[1];
+                    switch (paramName) {
+                        case "local-addr":
+                            this.localAddr = Short.parseShort(paramValue);
+                            break;
+                        case "remote-addr":
+                            this.remoteAddr = Short.parseShort(paramValue);
+                            break;
+                        default:
+                            logger.debug("Unknown parameter {} with value {}", paramName, paramValue);
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public boolean canRead() {
+        return true;
+    }
+
+    @Override
+    public boolean canWrite() {
+        return true;
+    }
+
+    @Override
+    protected ChannelHandler getChannelHandler(CompletableFuture<Void> sessionSetupCompleteFuture) {
+        return new ChannelInitializer() {
+            @Override
+            protected void initChannel(Channel channel) {
+                // Build the protocol stack for communicating with the s7 protocol.
+                ChannelPipeline pipeline = channel.pipeline();
+                pipeline.addLast(new ChannelInboundHandlerAdapter() {
+                    @Override
+                    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
+                        if (evt instanceof ConnectedEvent) {
+                            sessionSetupCompleteFuture.complete(null);
+                        } else {
+                            super.userEventTriggered(ctx, evt);
+                        }
+                    }
+                });
+                pipeline.addLast(new Df1Protocol(localAddr, remoteAddr));
+                pipeline.addLast(new Plc4XDf1Protocol());
+            }
+        };
+    }
+
+    @Override
+    public PlcReadRequest.Builder readRequestBuilder() {
+        return new DefaultPlcReadRequest.Builder(this, new Df1FieldHandler());
+    }
+
+    @Override
+    public PlcWriteRequest.Builder writeRequestBuilder() {
+        return new DefaultPlcWriteRequest.Builder(this, new Df1FieldHandler());
+    }
+
+    @Override
+    public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
+        CompletableFuture<InternalPlcReadResponse> future = new CompletableFuture<>();
+        PlcRequestContainer<InternalPlcReadRequest, InternalPlcReadResponse> container =
+            new PlcRequestContainer<>((InternalPlcReadRequest) readRequest, future);
+        channel.writeAndFlush(container).addListener(f -> {
+            if (!f.isSuccess()) {
+                future.completeExceptionally(f.cause());
+            }
+        });
+        return future
+            .thenApply(PlcReadResponse.class::cast);
+    }
+
+    @Override
+    public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
+        CompletableFuture<InternalPlcWriteResponse> future = new CompletableFuture<>();
+        PlcRequestContainer<InternalPlcWriteRequest, InternalPlcWriteResponse> container =
+            new PlcRequestContainer<>((InternalPlcWriteRequest) writeRequest, future);
+        channel.writeAndFlush(container).addListener(f -> {
+            if (!f.isSuccess()) {
+                future.completeExceptionally(f.cause());
+            }
+        });
+        return future
+            .thenApply(PlcWriteResponse.class::cast);
+    }
+
+}
diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/fields/DataType.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/fields/DataType.java
new file mode 100644
index 0000000..97b8b17
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/fields/DataType.java
@@ -0,0 +1,44 @@
+/*
+ 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.
+ */
+package org.apache.plc4x.java.amsads.fields;
+
+public enum DataType {
+    BIT((short)1),
+    BIT_STRING((short)-1),
+    BYTE_STRING((short)-1),
+    INTEGER((short)2),
+    TIMER((short)-1),
+    COUNTER((short)-1),
+    GENERAL_COUNT_STRUCTURE((short)-1),
+    FLOAT((short)-1),
+    ARRAY((short)-1),
+    ADDRESS((short)-1),
+    BINARY_CODED_DECIMAL((short)-1);
+
+    private final short length;
+
+    DataType(short length) {
+        this.length = length;
+    }
+
+    public short getLength() {
+        return length;
+    }
+
+}
diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/AMSADSProtocol.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/AMSADSProtocol.java
new file mode 100644
index 0000000..36aed20
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/AMSADSProtocol.java
@@ -0,0 +1,157 @@
+/*
+ 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.
+ */
+package org.apache.plc4x.java.df1.protocol;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.channel.ChannelHandlerContext;
+import org.apache.plc4x.java.api.exceptions.PlcProtocolException;
+import org.apache.plc4x.java.base.PlcByteToMessageCodec;
+import org.apache.plc4x.java.df1.readwrite.DF1Command;
+import org.apache.plc4x.java.df1.readwrite.DF1Symbol;
+import org.apache.plc4x.java.df1.readwrite.DF1SymbolMessageFrame;
+import org.apache.plc4x.java.df1.readwrite.io.DF1SymbolIO;
+import org.apache.plc4x.java.utils.ReadBuffer;
+import org.apache.plc4x.java.utils.WriteBuffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+public class AMSADSProtocol extends PlcByteToMessageCodec<AMSADSCommand> {
+
+    private static final Logger logger = LoggerFactory.getLogger(Df1Protocol.class);
+
+    private final short localAddr;
+    private final short remoteAddr;
+    private final DF1SymbolIO df1SymbolIO;
+
+    public Df1Protocol(short localAddr, short remoteAddr) {
+        this.localAddr = localAddr;
+        this.remoteAddr = remoteAddr;
+        df1SymbolIO = new DF1SymbolIO();
+    }
+
+    @Override
+    public void channelActive(ChannelHandlerContext ctx) throws Exception {
+    }
+
+    @Override
+    protected void encode(ChannelHandlerContext ctx, DF1Command msg, ByteBuf out) throws Exception {
+        // Create a new df1 frame for transmitting the command
+        DF1SymbolMessageFrame frame = new DF1SymbolMessageFrame(remoteAddr, localAddr, msg);
+
+        // Serialize the message
+        WriteBuffer writeBuffer = new WriteBuffer(frame.getLengthInBytes(), false);
+        df1SymbolIO.serialize(writeBuffer, frame);
+        byte[] data = writeBuffer.getData();
+
+        // Send the serialized data
+        // ctx.writeAndFlush(data);
+        out.writeBytes(data);
+    }
+
+    @Override
+    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
+        DF1Symbol resp;
+
+//        do {
+
+            in.markReaderIndex();
+
+            short size = 0x00;
+
+            // Yes, it's a little complicated, but we need to find out if we've got enough data.
+            if (in.readableBytes() > 1) {
+                if (in.getUnsignedByte(0) != (short) 0x10) {
+                    logger.warn("Expecting DF1 magic number: {}", 0x10);
+                    if (logger.isDebugEnabled()) {
+                        logger.debug("Got Data: {}", ByteBufUtil.hexDump(in));
+                    }
+                    exceptionCaught(ctx, new PlcProtocolException(
+                        String.format("Expecting DF1 magic number: %02X", 0x10)));
+                    return;
+                }
+
+                short symbolType = in.getUnsignedByte(1);
+                switch (symbolType) {
+                    case (short) 0x02: {
+                        if (in.readableBytes() < 5) {
+                            return;
+                        }
+                        short commandType = in.getUnsignedByte(4);
+                        switch (commandType) {
+                            case (short) 0x01: {
+                                if (in.readableBytes() < 11) {
+                                    return;
+                                }
+                                break;
+                            }
+                            case (short) 0x41: {
+                            /*int transactionCounter = in.getUnsignedShort(6);
+                            if(!readRequestSizes.containsKey(transactionCounter)) {
+                                logger.warn("Unknown transaction counter: {}", transactionCounter);
+                                if (logger.isDebugEnabled()) {
+                                    logger.debug("Got Data: {}", ByteBufUtil.hexDump(in));
+                                }
+                                exceptionCaught(ctx, new PlcProtocolException(
+                                    String.format("Unknown transaction counte: %04X", transactionCounter)));
+                                return;
+                            }
+                            size = readRequestSizes.remove(transactionCounter);
+                            if(in.readableBytes() < 8 + size) {
+                                return;
+                            }*/
+                                // TODO: Let's just assume all is good for now ...
+                                break;
+                            }
+                        }
+                        break;
+                    }
+                    case (short) 0x03: {
+                        if (in.readableBytes() < 4) {
+                            return;
+                        }
+                        break;
+                    }
+                }
+            }
+
+            // Parse the message received from the DF1 device
+            byte[] data = new byte[in.readableBytes()];
+            in.readBytes(data);
+            ReadBuffer readBuffer = new ReadBuffer(data, false);
+
+            resp = df1SymbolIO.parse(readBuffer);
+
+//        } while (readWasSucessfull);
+//        // TODO if unableto read
+//        in.resetReaderIndex();
+
+        // Add the received message to the output
+        out.add(resp);
+    }
+
+    @Override
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+        cause.printStackTrace();
+        ctx.close();
+        //super.exceptionCaught(ctx, cause);
+    }
+}
diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/Plc4XDf1Protocol.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/Plc4XDf1Protocol.java
new file mode 100644
index 0000000..d169dca
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/Plc4XDf1Protocol.java
@@ -0,0 +1,172 @@
+/*
+ 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.
+ */
+package org.apache.plc4x.java.df1.protocol;
+
+import io.netty.channel.ChannelHandlerContext;
+import org.apache.commons.lang3.NotImplementedException;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcRequest;
+import org.apache.plc4x.java.api.messages.PlcResponse;
+import org.apache.plc4x.java.api.messages.PlcWriteRequest;
+import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.types.PlcResponseCode;
+import org.apache.plc4x.java.base.PlcMessageToMessageCodec;
+import org.apache.plc4x.java.base.messages.DefaultPlcReadResponse;
+import org.apache.plc4x.java.base.messages.InternalPlcReadRequest;
+import org.apache.plc4x.java.base.messages.PlcRequestContainer;
+import org.apache.plc4x.java.base.messages.items.BaseDefaultFieldItem;
+import org.apache.plc4x.java.base.messages.items.DefaultIntegerFieldItem;
+import org.apache.plc4x.java.df1.*;
+import org.apache.plc4x.java.df1.readwrite.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class Plc4XDf1Protocol extends PlcMessageToMessageCodec<DF1Symbol, PlcRequestContainer> {
+
+    private static final Logger logger = LoggerFactory.getLogger(Plc4XDf1Protocol.class);
+
+    private final AtomicInteger transactionId = new AtomicInteger(1);
+    private Map<Integer, PlcRequestContainer> requests = new ConcurrentHashMap<>();
+
+    @Override
+    protected void encode(ChannelHandlerContext ctx, PlcRequestContainer msg, List<Object> out) throws Exception {
+        logger.trace("Received Request {} to send out", msg);
+        if (msg.getRequest() instanceof PlcReadRequest) {
+            for (PlcField field : ((PlcReadRequest) msg.getRequest()).getFields()) {
+                if (!(field instanceof Df1Field)) {
+                    throw new IllegalArgumentException("Invalid field type found inside Df1 Request");
+                }
+                int address = ((Df1Field) field).getAddress();
+                short size = ((Df1Field) field).getDataType().getLength();
+                int transactionId = this.transactionId.getAndIncrement();
+                while (((transactionId & 0xFF) == 0x10) || (((transactionId >>> 8) & 0xFF) == 0x10)) {
+                    // prevent that one of the transactionID bytes is 0x10, which has to be escaped by double 0x10 and makes life a lot harder
+                    transactionId = this.transactionId.getAndIncrement();
+                }
+                logger.debug("Creating request for offset {}, with length {} and transaction id {}", address, size, transactionId);
+
+                requests.put(transactionId, msg);
+
+                switch (((Df1Field) field).getAddress_type()) {
+                    case OFFSET:
+                        out.add(new DF1UnprotectedReadRequest((short) 0x00, (short)transactionId, address, size));
+                        break;
+                    case LOGICAL:
+                        // TODO: add 'protected typed logical read' to mspec
+                        throw new NotImplementedException("not yet implemented in mspec");
+                }
+
+            }
+        } else {
+            throw new IllegalStateException("This should not happen!");
+        }
+    }
+
+    @Override
+    protected void decode(ChannelHandlerContext ctx, DF1Symbol msg, List<Object> out) throws Exception {
+        logger.debug("Received DF1 Command incoming {}", msg);
+
+        if (msg instanceof DF1SymbolMessageFrameNAK) {
+            logger.warn("Received a response NAK, notify all requests");
+            for (Map.Entry<Integer, PlcRequestContainer> entry : requests.entrySet()) {
+                entry.getValue().getResponseFuture().complete(
+                    new DefaultPlcReadResponse(
+                        ((InternalPlcReadRequest) entry.getValue().getRequest()),
+                        Collections.singletonMap("erster", Pair.of(PlcResponseCode.INTERNAL_ERROR, new DefaultIntegerFieldItem(-1)))
+                    ));
+            }
+            return;
+        } else if (msg instanceof DF1SymbolMessageFrameACK) {
+            logger.warn("Received a response ACK :D");
+            return;
+        }
+
+        assert msg instanceof DF1SymbolMessageFrame;
+
+        DF1Command command = ((DF1SymbolMessageFrame) msg).getCommand();
+        int transactionId = command.getTransactionCounter();
+        if (!requests.containsKey(transactionId)) {
+            logger.warn("Received a response to unknown transaction id {}", transactionId);
+            ctx.fireExceptionCaught(new RuntimeException("Received a response to unknown transaction id"));
+            ctx.close();
+            return;
+        }
+        // As every response has a matching request, get this request based on the tpdu.
+        PlcRequestContainer requestContainer = requests.remove(transactionId);
+        PlcRequest request = requestContainer.getRequest();
+
+        // Handle the response.
+        PlcResponse response = null;
+        if (request instanceof PlcReadRequest) {
+            /*
+            Things to do
+            - check response code (if there is something like that?
+            - cast the bytes to right datatype
+            - create Response
+             */
+            // We can do this as we have only one fieldName in DF1
+            final String fieldName = ((PlcReadRequest) request).getFieldNames().iterator().next();
+            // TODO can there be another code than ok?
+            final PlcResponseCode responseCode = PlcResponseCode.OK;
+            // TODO maybe check for different status bytes
+            final Df1Field field = (Df1Field) ((PlcReadRequest) request).getField(fieldName);
+            // Cast byte and create response item
+            BaseDefaultFieldItem responseItem = null;
+            short[] data = ((DF1UnprotectedReadResponse)command).getData();
+            switch (field.getDataType()) {
+                case BIT:
+                    break;
+                case INTEGER:
+                    // TODO: type conversion is untested
+                    responseItem = new DefaultIntegerFieldItem((int)data[0] + ((int) data[1] << 8));
+                    break;
+                case FLOAT:
+                    break;
+                case BIT_STRING:
+                    break;
+                case ARRAY:
+                    break;
+                // TODO add all other cases here...
+                default:
+                    throw new NotImplementedException("The DataType " + field.getDataType() + " is currently not implemented!");
+            }
+            response = new DefaultPlcReadResponse(((InternalPlcReadRequest) request),
+                Collections.singletonMap(fieldName,
+                    Pair.of(responseCode, responseItem)));
+        } else if (request instanceof PlcWriteRequest) {
+            logger.warn("Writing is currently not implemented but received a write response?!");
+            ctx.close();
+            throw new NotImplementedException("This is currently not implemented!");
+        }
+
+        // Confirm the response being handled.
+        if (response != null) {
+            requestContainer.getResponseFuture().complete(response);
+        }
+    }
+
+
+}
diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/util/DF1Utils.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/util/DF1Utils.java
new file mode 100644
index 0000000..820517e
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/util/DF1Utils.java
@@ -0,0 +1,158 @@
+/*
+ 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.
+ */
+package org.apache.plc4x.java.df1.util;
+
+import org.apache.plc4x.java.df1.readwrite.DF1Command;
+import org.apache.plc4x.java.df1.readwrite.DF1UnprotectedReadRequest;
+import org.apache.plc4x.java.df1.readwrite.DF1UnprotectedReadResponse;
+import org.apache.plc4x.java.utils.ParseException;
+import org.apache.plc4x.java.utils.ReadBuffer;
+import org.apache.plc4x.java.utils.WriteBuffer;
+
+public class DF1Utils {
+
+    public static short crcCheck(Object... args) {
+        short destinationAddress = (short) args[0];
+        short sourceAddress = (short) args[1];
+        DF1Command command = (DF1Command) args[2];
+        short commandDiscriminatorValues = (short) command.getDiscriminatorValues()[0];
+        short status = command.getStatus();
+        int transactionCounter = command.getTransactionCounter();
+        if(command instanceof DF1UnprotectedReadRequest) {
+            try {
+                DF1UnprotectedReadRequest unprotectedReadRequest = (DF1UnprotectedReadRequest) command;
+                WriteBuffer writeBuffer = new WriteBuffer(10, false);
+                writeBuffer.writeUnsignedShort(8, destinationAddress);
+                writeBuffer.writeUnsignedShort(8, sourceAddress);
+                writeBuffer.writeUnsignedShort(8, commandDiscriminatorValues);
+                writeBuffer.writeUnsignedShort(8, status);
+                writeBuffer.writeUnsignedInt(16, (short) transactionCounter);
+                writeBuffer.writeUnsignedInt(16, (short) unprotectedReadRequest.getAddress());
+                writeBuffer.writeUnsignedShort(8, (byte) unprotectedReadRequest.getSize());
+                writeBuffer.writeUnsignedShort(8, (byte) 0x03);
+
+                byte[] data = writeBuffer.getData();
+                return calculateCRC(data);
+
+            } catch (ParseException e) {
+                throw new RuntimeException("Something went wrong during the CRC check", e);
+            }
+        } else if(command instanceof DF1UnprotectedReadResponse) {
+            DF1UnprotectedReadResponse unprotectedReadResponseCommand = (DF1UnprotectedReadResponse) command;
+            try {
+                // TODO: size has to be dependent on actual size requested
+                WriteBuffer writeBuffer = new WriteBuffer(10, false);
+                writeBuffer.writeUnsignedShort(8, destinationAddress);
+                writeBuffer.writeUnsignedShort(8, sourceAddress);
+                writeBuffer.writeUnsignedShort(8, commandDiscriminatorValues);
+                writeBuffer.writeUnsignedShort(8, status);
+                writeBuffer.writeUnsignedInt(16, (short) transactionCounter);
+                boolean escape10 = false;
+                for (short data : unprotectedReadResponseCommand.getData()) {
+//                    if (escape10 == true){
+//                        if (data == 0x10) {
+//
+//                        }
+//                    } else{
+//
+//                    }
+                    writeBuffer.writeUnsignedShort(8,  data);
+                }
+                writeBuffer.writeUnsignedShort(8, (byte) 0x03);
+
+                byte[] data = writeBuffer.getData();
+                return calculateCRC(data);
+
+            } catch (ParseException e) {
+                throw new RuntimeException("Something went wrong during the CRC check", e);
+            }
+        }
+
+        return 0;
+    }
+
+    public static boolean dataTerminate(ReadBuffer io) {
+        try {
+            // The byte sequence 0x10 followed by 0x03 indicates the end of the message,
+            // so if we would read this, we abort the loop and stop reading data.
+            if ((io.peekByte(0) == (byte) 0x10) && (io.peekByte(1) == (byte) 0x03)) {
+                return true;
+            }
+        } catch (ParseException e) {
+            // Just ignore and return false.
+        }
+        return false;
+    }
+
+    public static short readData(ReadBuffer io) {
+        try {
+            // If we read a 0x10, this has to be followed by another 0x10, which is how
+            // this value is escaped in DF1, so if we encounter two 0x10, we simply ignore the first.
+            if ((io.peekByte(0) == (byte) 0x10) && (io.peekByte(1) == 0x10)) {
+                io.readByte(8);
+            }
+            return io.readUnsignedShort(8);
+        } catch (ParseException e) {
+            throw new RuntimeException("Error parsing data", e);
+        }
+    }
+
+    public static void writeData(WriteBuffer io, short data) {
+        try {
+            // If a value is 0x10, this has to be duplicated in order to be escaped.
+            if ((data == (short) 0x10)) {
+                io.writeUnsignedShort(8, (short) 0x10);
+            }
+            io.writeUnsignedShort(8, data);
+        } catch (ParseException e) {
+            throw new RuntimeException("Error parsing data", e);
+        }
+    }
+
+    public static int dataLength(short[] data) {
+        int i = 0;
+        for(short dataByte : data) {
+            // If a value is 0x10, this has to be duplicated which increases the message size by one.
+            if(dataByte == 0x10) {
+                i++;
+            }
+            i++;
+        }
+        return i;
+    }
+
+    private static short calculateCRC(byte[] crcBytes) {
+        int tmp = 0;
+        int crcL, crcR;
+
+        for (int newByte : crcBytes) {
+            crcL = tmp >> 8;
+            crcR = tmp & 0xFF;
+            tmp = (crcL << 8) + (newByte ^ crcR);
+            for (int j = 0; j < 8; j++)
+                if (tmp % 2 == 1) {     // check if LSB shifted out is 1 or 0
+                    tmp = tmp >> 1;
+                    tmp = tmp ^ 0xA001;
+                } else {
+                    tmp = tmp >> 1;
+                }
+        }
+        return (short)tmp;
+    }
+}
diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/util/Df1FieldHandler.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/util/Df1FieldHandler.java
new file mode 100644
index 0000000..4b92194
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/util/Df1FieldHandler.java
@@ -0,0 +1,39 @@
+/*
+ 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.
+ */
+package org.apache.plc4x.java.df1.util;
+
+import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.base.connection.DefaultPlcFieldHandler;
+import org.apache.plc4x.java.base.messages.items.BaseDefaultFieldItem;
+import org.apache.plc4x.java.df1.Df1Field;
+
+public class Df1FieldHandler extends DefaultPlcFieldHandler {
+
+    @Override
+    public PlcField createField(String fieldQuery) throws PlcInvalidFieldException {
+        return Df1Field.of(fieldQuery);
+    }
+
+    @Override
+    public BaseDefaultFieldItem encodeByte(PlcField field, Object[] values) {
+        return super.encodeByte(field, values);
+    }
+
+}
diff --git a/sandbox/test-java-amsads-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.PlcDriver b/sandbox/test-java-amsads-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.PlcDriver
new file mode 100644
index 0000000..f59c2cd
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.PlcDriver
@@ -0,0 +1,38 @@
+#
+# 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.
+#
+
+#
+# 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.
+#
+org.apache.plc4x.java.amsads.AMSADSPlcDriver
diff --git a/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/java/amsads/AMSADSPlcDriverTest.java b/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/java/amsads/AMSADSPlcDriverTest.java
new file mode 100644
index 0000000..5057086
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/java/amsads/AMSADSPlcDriverTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+package org.apache.plc4x.java.df1;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.regex.Matcher;
+
+import static org.apache.plc4x.java.df1.DF1PlcDriver.DF1_URI_PATTERN;
+import static org.apache.plc4x.java.df1.DF1PlcDriver.SERIAL_PATTERN;
+
+public class AMSADSPlcDriverTest {
+
+    @Test
+    public void matchExpression() {
+        Matcher matcher = SERIAL_PATTERN.matcher("serial:///COM4");
+
+        Assertions.assertTrue(matcher.matches());
+    }
+
+    @Test
+    public void matchExpression2() {
+        Matcher matcher = DF1_URI_PATTERN.matcher("df1:serial:///COM4");
+
+        Assertions.assertTrue(matcher.matches());
+    }
+}
\ No newline at end of file
diff --git a/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/BenchmarkGeneratedDf1.java b/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/BenchmarkGeneratedDf1.java
new file mode 100644
index 0000000..27c9be2
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/BenchmarkGeneratedDf1.java
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+package org.apache.plc4x.protocol.df1;
+
+import com.fazecast.jSerialComm.SerialPort;
+import org.apache.plc4x.java.df1.*;
+import org.apache.plc4x.java.utils.ReadBuffer;
+import org.apache.plc4x.java.utils.WriteBuffer;
+
+public class BenchmarkGeneratedDf1 {
+
+    public static void main(String[] args) throws Exception {
+        /*// Manually build a message
+        ReadRequest readRequest = new ReadRequest(new DF1SymbolMessageFrameStart((short) 0x09, (short) 0x00, new DF1ReadRequest((short) 0x00, 0x01, 0x0B, (short) 0x02)), new DF1SymbolMessageFrameEnd());
+
+        // Serialize the message
+        WriteBuffer writeBuffer = new WriteBuffer(100, false);
+        new ReadRequestIO().serialize(writeBuffer, readRequest);
+        byte[] data = writeBuffer.getData();
+
+        // Send the serialized message to the PLC via COM port
+        SerialPort comPort = SerialPort.getCommPort("/dev/cu.usbserial-AL065SUZ");
+        comPort.openPort();
+        comPort.setComPortParameters(19200, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY);
+        comPort.writeBytes(data, 20);
+
+        // Give the PLC some time to respond.
+        while (comPort.bytesAvailable() == 0) {
+            Thread.sleep(22);
+        }
+
+        // Read the response
+        byte[] readBytes = new byte[comPort.bytesAvailable()];
+        comPort.readBytes(readBytes, readBytes.length);
+
+        // Parse the ACK/NACK response
+        ReadBuffer readBuffer = new ReadBuffer(readBytes);
+        Result result = new ResultIO().parse(readBuffer);
+
+        // Check if the response was an ACK
+        if(result.getResult() instanceof DF1SymbolMessageFrameACK) {
+            // The actual result is sent with a little delay.
+            while (comPort.bytesAvailable() == 0) {
+                Thread.sleep(22);
+            }
+
+            // Read the actual response data
+            readBytes = new byte[comPort.bytesAvailable()];
+            comPort.readBytes(readBytes, readBytes.length);
+
+            // Parse the response
+            readBuffer = new ReadBuffer(readBytes);
+            ReadResponse readResponse = new ReadResponseIO().parse(readBuffer, (short) 0x02);
+
+            // So something senseless ;-)
+            System.out.println(readResponse);
+        } else {
+            System.out.println("Didn't get an ACK");
+        }
+
+        comPort.closePort();*/
+    }
+
+}
diff --git a/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/BenchmarkManualDf1.java b/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/BenchmarkManualDf1.java
new file mode 100644
index 0000000..7e4141b
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/BenchmarkManualDf1.java
@@ -0,0 +1,239 @@
+/*
+ * 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.
+ */
+
+package org.apache.plc4x.protocol.df1;
+
+import com.fazecast.jSerialComm.SerialPort;
+
+public class BenchmarkManualDf1 {
+
+    public static void main(String[] args) throws Exception {
+//        byte[] rData = Hex.decodeHex("0300006702f080320100000001005600000407120a10060001032b84000160120a10020001032b840001a0120a10010001032b840001a9120a10050001032b84000150120a10020001032b84000198120a10040001032b84000140120a10020001032b84000190");
+//        long start = System.currentTimeMillis();
+//        int numRunsParse = 2000000;
+//        TPKTPacketIO tpktPacketIO = new TPKTPacketIO();
+//
+//
+//        CommPortIdentifier id = CommPortIdentifier.getPortIdentifier("");
+//
+//
+//        // Benchmark the parsing code
+//        TPKTPacket packet = null;
+//        for(int i = 0; i < numRunsParse; i++) {
+//            ReadBuffer rBuf = new ReadBuffer(rData);
+//            packet = tpktPacketIO.parse(rBuf);
+//        }
+//        long endParsing = System.currentTimeMillis();
+//
+//        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 numRunsSerialize = 2000000;
+//        byte[] oData = null;
+//        for(int i = 0; i < numRunsSerialize; i++) {
+//            WriteBuffer wBuf = new WriteBuffer(packet.getLengthInBytes());
+//            tpktPacketIO.serialize(wBuf, packet);
+//            oData = wBuf.getData();
+//        }
+//        long endSerializing = System.currentTimeMillis();
+//
+//        System.out.println("Serialized " + numRunsSerialize + " packets in " + (endSerializing - endParsing) + "ms");
+//        System.out.println("That's " + ((float) (endSerializing - endParsing) / numRunsSerialize) + "ms per packet");
+//        if(!Arrays.equals(rData, oData)) {
+//            for(int i = 0; i < rData.length; i++) {
+//                if(rData[i] != oData[i]) {
+//                    System.out.println("Difference in byte " + i);
+//                }
+//            }
+//            System.out.println("Not equals");
+//        } else {
+//            System.out.println("Bytes equal");
+//        }
+
+
+//        byte[] rData = {0x10, 0x02, 0x00, 0x09, 0x41, 0x00, 0x01, 0x00, 0x1F, 0x1F, 0x10, 0x03, 0x1A, 0x2B};
+//
+//        DF1SymbolIO df1SymbolIO = new DF1SymbolIO();
+//        DF1Symbol packet;
+//        ReadBuffer rBuf = new ReadBuffer(rData);
+//        int statusWord = (rData[7]<<8) + rData[6];
+//        DF1Command messageCommand = new DF1Command((short)rData[5]); //,(short)statusWord);
+//        DF1SymbolMessageFrameStart messageStart = new DF1SymbolMessageFrameStart((short)rData[3],(short)rData[2], messageCommand);
+//        packet = df1SymbolIO.parse(rBuf, (short) (rData.length-12), messageStart);
+//
+//        System.out.println("x: " + packet);
+//        System.exit(0);
+
+
+
+        SerialPort comPort = SerialPort.getCommPorts()[0];
+        comPort.openPort();
+
+        comPort.setComPortParameters(19200, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY);
+//        comPort.setComPortTimeouts(SerialPort.TIMEOUT_NONBLOCKING, 0, 0);
+
+        System.out.print(comPort.getSystemPortName() + " | ");
+        //System.out.print(comPort.getPortDescription() + " | ");
+        System.out.print(comPort.getDescriptivePortName() + " | Baud rate: ");
+        System.out.println(comPort.getBaudRate());
+//        System.out.println(comPort.getReadTimeout());
+//        System.out.println(comPort.getWriteTimeout());
+
+
+
+//        DF1SymbolIO df1message = new DF1SymbolIO();
+
+
+        byte[] c_STX = {0x02};
+        byte[] c_SOH = {0x01};
+        byte[] c_ETX = {0x03};
+        byte[] c_EOT = {0x04};
+        byte[] c_ENQ = {0x05};
+        byte[] c_ACK = {0x06};
+        byte[] c_DLE = {0x10};
+        byte[] c_NAK = {0x0f};
+
+        byte[] c_DST = {0x09};
+        byte[] c_SRC = {0x00};
+        byte[] c_CMD = {0x06};
+        byte[] c_FNC = {0x03};
+        byte[] c_STS = {0x00};
+        byte[] c_TNS = {0x01, 0x00};
+        byte[] c_ADR = {0x11, 0x00};
+        byte[] c_SZE = {0x02};
+//        byte[] c_BCC = {-30};
+
+//        byte[] c_STN = {0x11};
+//        byte[] c_DST = {0x01};
+//        byte[] c_SRC = {0x00};
+//        byte[] c_SZE = {0x0c};
+//        byte[] c_TNS = {0x41, 0x00};
+//        byte[] c_ADR = {0x12, 0x00};
+//        byte[] c_CRC = {-49, 0x40};
+
+
+//        byte[] message = {0x10, 0x01, 0x11, 0x10, 0x02, 0x09, 0x00, 0x01, 0x00, 0x41, 0x00, 0x12, 0x00, 0x0c, 0x10, 0x03}; // halfduplex msg
+//        comPort.writeBytes(message, message.length);
+
+//        byte[] message = {0x10, 0x05, 0x11, -17};         // halfduplex poll
+//        comPort.writeBytes(message, message.length);
+
+
+//        comPort.writeBytes(c_DLE, 1);     // fullduplex msg Seite 235
+//        comPort.writeBytes(c_STX, 1);
+//        comPort.writeBytes(c_DST, 1);
+//        comPort.writeBytes(c_SRC, 1);
+//        comPort.writeBytes(c_CMD, 1);
+//        comPort.writeBytes(c_STS, 1);
+//        comPort.writeBytes(c_TNS, 2);
+//        comPort.writeBytes(c_FNC, 1);
+//        comPort.writeBytes(c_ADR, 2);
+//        comPort.writeBytes(c_SZE, 1);
+//        comPort.writeBytes(c_DLE, 1);
+//        comPort.writeBytes(c_ETX, 1);
+
+        byte[] msg = {0x10, 0x02,   0x09, 0x00,   0x01, 0x00,   0x01, 0x00,   0x0b, 0x00,   0x02,   0x10, 0x03};
+        comPort.writeBytes(msg, 13);
+
+
+//        int[] crcmsg = {c_DST[0], c_SRC[0], c_CMD[0], c_STS[0], c_TNS[0], c_TNS[1], c_ADR[0], c_ADR[1], c_SZE[0], c_ETX[0]}; // fullduplex CRC
+//        int[] crcmsg = {c_DST[0], c_SRC[0], c_CMD[0], c_STS[0], c_TNS[0], c_TNS[1], c_FNC[0], c_ETX[0]};                       // diagnostic status request
+//        int[] crcmsg = {0x11, 0x02, 0x09, 0x00, 0x01, 0x00, 0x41, 0x00, 0x12, 0x00, 0x0c, 0x03}; // halfduplex CRC
+        int[] crcmsg = { 0x09, 0x00,   0x01, 0x00,   0x01, 0x00,   0x0b, 0x00,   0x02,   0x03};
+
+        int[] c_CRC = CalcCRC(crcmsg);
+        byte[] crc1 = {(byte)c_CRC[0]};
+        byte[] crc2 = {(byte)c_CRC[1]};
+        System.out.println("crc1: " + Integer.toHexString(crc1[0]));
+        System.out.println("crc2: " + Integer.toHexString(crc2[0]));
+        comPort.writeBytes(crc1, 1);
+        comPort.writeBytes(crc2, 1);
+
+
+        while (comPort.bytesAvailable() == 0) {
+            Thread.sleep(22); }
+
+        byte[] readBuffer = new byte[comPort.bytesAvailable()];
+        int numRead = comPort.readBytes(readBuffer, readBuffer.length);
+        System.out.println("Read " + numRead + " bytes.");
+
+        for (byte c_RCV : readBuffer) {
+            System.out.print(Integer.toHexString(c_RCV) + " | "); }
+        System.out.println("");
+
+//        if (numRead > 1) {
+//            if (readBuffer[1] != 0x15) {
+//                comPort.writeBytes(c_DLE, 1);
+//                comPort.writeBytes(c_ACK, 1);
+//            }
+//        }
+
+        while (comPort.bytesAvailable() == 0) {
+            Thread.sleep(22); }
+
+
+        byte[] readBuffer2 = new byte[comPort.bytesAvailable()];
+        int numRead2 = comPort.readBytes(readBuffer2, readBuffer2.length);
+        System.out.println("Read " + numRead2 + " bytes.");
+
+        for (byte c_RCV2 : readBuffer2) {
+            System.out.print(Integer.toHexString(c_RCV2) + " | "); }
+        System.out.println("");
+
+        comPort.closePort();
+
+    }
+
+        private static int[] CalcCRC(int[] crcBytes) {
+            int tmp = 0;
+            int crcL, crcR;
+
+            for (int newByte : crcBytes ) {
+                crcL = tmp >> 8;
+                crcR = tmp & 0xFF;
+                tmp = (crcL << 8) + (newByte ^ crcR);
+                for (int j=0; j<8; j++)
+                    if (tmp % 2 == 1) {     // check if LSB shifted out is 1 or 0
+                        tmp = tmp >> 1;
+                        tmp = tmp ^ 0xA001;
+                    } else {
+                        tmp = tmp >> 1;
+                    }
+            }
+
+//            return ((tmp & 0xFF) << 8) + (tmp >> 8);  // returns lowbyte|highbyte as one number, change return to non-array
+
+            int[] tmparray = {(tmp & 0xFF), (tmp >> 8)};
+            return tmparray;
+        }
+
+        private static int CalcBCC(int[] crcBytes) {
+            int tmp = 0;
+            int j = 0;
+
+            for (int newByte : crcBytes) {
+                tmp = tmp + newByte;
+                if (newByte == 0x10) {
+                    j = ++j; }
+            }
+            tmp = tmp - ((j/2) * 0x10);  // get rid of double DLE
+            return ((~tmp) & 0b11111111) + 1;
+        }
+}
diff --git a/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/Df1Test.java b/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/Df1Test.java
new file mode 100644
index 0000000..bcadf1a
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/Df1Test.java
@@ -0,0 +1,30 @@
+/*
+  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.
+*/
+
+package org.apache.plc4x.protocol.df1;
+
+import org.apache.plc4x.protocol.test.ProtocolTestsuiteRunner;
+
+public class Df1Test extends ProtocolTestsuiteRunner {
+
+    public Df1Test() {
+        super("/testsuite/Df1Testsuite.xml");
+    }
+
+}
diff --git a/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/EndToEndTest.java b/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/EndToEndTest.java
new file mode 100644
index 0000000..42e2635
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/EndToEndTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package org.apache.plc4x.protocol.df1;
+
+import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
+import org.junit.jupiter.api.Test;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * TODO write comment
+ *
+ * @author julian
+ * Created by julian on 2019-08-07
+ */
+public class EndToEndTest {
+
+    @Test
+    public void helloDf1() {
+        try (PlcConnection plcConnection = new PlcDriverManager().getConnection("df1:serial:///COM4")) {
+            PlcReadRequest request = plcConnection.readRequestBuilder()
+                .addItem("hurz", "5:INTEGER")
+                .build();
+
+            PlcReadResponse response = request.execute().get(100, TimeUnit.SECONDS);
+
+
+            // TODO: get the actual read bytes from the response
+            System.out.println(response);
+            System.out.println("Response code was " + response.getResponseCode("erster"));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/IOTest.java b/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/IOTest.java
new file mode 100644
index 0000000..6179b7f
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/IOTest.java
@@ -0,0 +1,99 @@
+/*
+ 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.
+ */
+
+package org.apache.plc4x.protocol.df1;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.plc4x.java.df1.readwrite.DF1Symbol;
+import org.apache.plc4x.java.df1.readwrite.io.DF1SymbolIO;
+import org.apache.plc4x.java.utils.ReadBuffer;
+import org.junit.jupiter.api.Test;
+
+public class IOTest {
+
+    @Test
+    public void testXml() throws Exception {
+        byte[] rData = Hex.decodeHex("10020900010001001100021003546F");
+        ObjectMapper mapper = new XmlMapper().enableDefaultTyping();
+        ReadBuffer rBuf = new ReadBuffer(rData, false);
+        DF1Symbol symbol = new DF1SymbolIO().parse(rBuf);
+        String xml = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(symbol);
+        System.out.println(xml);
+        DF1Symbol symbol2 = mapper.readValue(xml, DF1Symbol.class);
+        System.out.println(symbol2);
+    }
+
+    @Test
+    public void testJson() throws Exception {
+        byte[] rData = Hex.decodeHex("10020A0941000100FFFF1003DFB9");
+        ObjectMapper mapper = new ObjectMapper().enableDefaultTyping();
+        ReadBuffer rBuf = new ReadBuffer(rData, false);
+        DF1Symbol symbol = new DF1SymbolIO().parse(rBuf);
+        String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(symbol);
+        System.out.println(json);
+        DF1Symbol symbol2 = mapper.readValue(json, DF1Symbol.class);
+        System.out.println(symbol2);
+    }
+
+    /*@Test
+    public void testParser() throws Exception {
+        byte[] rData = Hex.decodeHex("0610020500180801c0a82a46c4090801c0a82a46c40a0203");
+        long start = System.currentTimeMillis();
+        int numRunsParse = 20000;
+
+        KNXNetIPMessageIO knxNetIPMessageIO = new KNXNetIPMessageIO();
+
+        // Benchmark the parsing code
+        KNXNetIPMessage packet = null;
+        for(int i = 0; i < numRunsParse; i++) {
+            ReadBuffer rBuf = new ReadBuffer(rData);
+            packet = knxNetIPMessageIO.parse(rBuf);
+        }
+        long endParsing = System.currentTimeMillis();
+
+        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 numRunsSerialize = 20000;
+        byte[] oData = null;
+        for(int i = 0; i < numRunsSerialize; i++) {
+            WriteBuffer wBuf = new WriteBuffer(packet.getLengthInBytes());
+            knxNetIPMessageIO.serialize(wBuf, packet);
+            oData = wBuf.getData();
+        }
+        long endSerializing = System.currentTimeMillis();
+
+        System.out.println("Serialized " + numRunsSerialize + " packets in " + (endSerializing - endParsing) + "ms");
+        System.out.println("That's " + ((float) (endSerializing - endParsing) / numRunsSerialize) + "ms per packet");
+        if(!Arrays.equals(rData, oData)) {
+            for(int i = 0; i < rData.length; i++) {
+                if(rData[i] != oData[i]) {
+                    System.out.println("Difference in byte " + i);
+                }
+            }
+            System.out.println("Not equals");
+        } else {
+            System.out.println("Bytes equal");
+        }
+    }*/
+
+}
diff --git a/sandbox/test-java-amsads-driver/src/test/resources/testsuite/Df1Testsuite.xml b/sandbox/test-java-amsads-driver/src/test/resources/testsuite/Df1Testsuite.xml
new file mode 100644
index 0000000..27dcbec
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/src/test/resources/testsuite/Df1Testsuite.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+<test:testsuite xmlns:test="https://plc4x.apache.org/schemas/testsuite.xsd"
+                bigEndian="true">
+
+  <name>Allen-Bradley DF1</name>
+
+  <testcase>
+    <name>Unprotected Read Address Request</name>
+    <raw>10020900010001001100021003546F</raw>
+    <root-type>DF1Symbol</root-type>
+    <xml>
+      <DF1SymbolMessageFrame className="org.apache.plc4x.java.df1.readwrite.DF1SymbolMessageFrame">
+        <destinationAddress>9</destinationAddress>
+        <sourceAddress>0</sourceAddress>
+        <command className="org.apache.plc4x.java.df1.readwrite.DF1UnprotectedReadRequest">
+          <status>0</status>
+          <transactionCounter>1</transactionCounter>
+          <address>17</address>
+          <size>2</size>
+        </command>
+      </DF1SymbolMessageFrame>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Unprotected Read Address Response</name>
+    <raw>10020A0941000100FFFF1003DFB9</raw>
+    <root-type>DF1Symbol</root-type>
+    <xml>
+      <DF1SymbolMessageFrame className="org.apache.plc4x.java.df1.readwrite.DF1SymbolMessageFrame">
+        <destinationAddress>10</destinationAddress>
+        <sourceAddress>9</sourceAddress>
+        <command className="org.apache.plc4x.java.df1.readwrite.DF1UnprotectedReadResponse">
+          <status>0</status>
+          <transactionCounter>1</transactionCounter>
+          <data>
+            <data>255</data>
+            <data>255</data>
+          </data>
+        </command>
+      </DF1SymbolMessageFrame>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Unprotected Read Address Response (Containing 0x10 in the data)</name>
+    <raw>10020A09410001001010FF1003BAAD</raw>
+    <root-type>DF1Symbol</root-type>
+    <xml>
+      <DF1SymbolMessageFrame className="org.apache.plc4x.java.df1.readwrite.DF1SymbolMessageFrame">
+        <destinationAddress>10</destinationAddress>
+        <sourceAddress>9</sourceAddress>
+        <command className="org.apache.plc4x.java.df1.readwrite.DF1UnprotectedReadResponse">
+          <status>0</status>
+          <transactionCounter>1</transactionCounter>
+          <data>
+            <data>16</data>
+            <data>255</data>
+          </data>
+        </command>
+      </DF1SymbolMessageFrame>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>ACK Response</name>
+    <raw>1006</raw>
+    <root-type>DF1Symbol</root-type>
+    <xml>
+      <DF1SymbolMessageFrameACK className="org.apache.plc4x.java.df1.readwrite.DF1SymbolMessageFrameACK"/>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>NACK Response</name>
+    <raw>1015</raw>
+    <root-type>DF1Symbol</root-type>
+    <xml>
+      <DF1SymbolMessageFrameNAK className="org.apache.plc4x.java.df1.readwrite.DF1SymbolMessageFrameNAK"/>
+    </xml>
+  </testcase>
+
+</test:testsuite>
\ No newline at end of file


[plc4x] 03/07: cleanup tests and reformat code

Posted by sr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch feature/ams_ads_mpsec
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 877319f0bfa9996ea1cae5d501673d079ff60862
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Nov 29 12:00:02 2019 +0100

    cleanup tests and reformat code
---
 .../mspec/expression/ExpressionStringListener.java |  32 ++--
 .../mspec/expression/ExpressionStringParser.java   |  14 +-
 .../definitions/DefaultComplexTypeDefinition.java  |   8 +-
 .../DefaultDiscriminatedComplexTypeDefinition.java |   2 +-
 .../definitions/DefaultEnumTypeDefinition.java     |   2 +-
 .../mspec/parser/MessageFormatListener.java        |  70 ++++-----
 .../language/mspec/parser/MessageFormatParser.java |  45 +-----
 .../mspec/parser/MessageFormatListenerTest.java    | 162 ---------------------
 .../mspec/parser/MessageFormatParserTest.java      |  44 +-----
 9 files changed, 67 insertions(+), 312 deletions(-)

diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringListener.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringListener.java
index bec1f9d..f4ae9e3 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringListener.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringListener.java
@@ -45,10 +45,10 @@ public class ExpressionStringListener extends ExpressionBaseListener {
     @Override
     public void exitExpressionString(ExpressionParser.ExpressionStringContext ctx) {
         List<Term> roots = parserContexts.pop();
-        if(roots.isEmpty()) {
+        if (roots.isEmpty()) {
             throw new RuntimeException("Empty Expression not supported.");
         }
-        if(roots.size() != 1) {
+        if (roots.size() != 1) {
             throw new RuntimeException("Expression can only contain one root term.");
         }
         root = roots.get(0);
@@ -65,13 +65,13 @@ public class ExpressionStringListener extends ExpressionBaseListener {
 
     @Override
     public void exitBoolExpression(ExpressionParser.BoolExpressionContext ctx) {
-        parserContexts.peek().add(new BooleanLiteral(Boolean.valueOf(ctx.getText())));
+        parserContexts.peek().add(new BooleanLiteral(Boolean.parseBoolean(ctx.getText())));
     }
 
     @Override
     public void exitNumberExpression(ExpressionParser.NumberExpressionContext ctx) {
         String strValue = ctx.Number().getText();
-        if(strValue.contains(".")) {
+        if (strValue.contains(".")) {
             parserContexts.peek().add(new NumericLiteral(Double.valueOf(strValue)));
         } else {
             parserContexts.peek().add(new NumericLiteral(Long.valueOf(strValue)));
@@ -95,11 +95,11 @@ public class ExpressionStringListener extends ExpressionBaseListener {
         IndexContext indexContext = null;
         RestContext restContext = null;
         for (Term arg : args) {
-            if(arg instanceof ArgsContext) {
+            if (arg instanceof ArgsContext) {
                 argsContext = (ArgsContext) arg;
-            } else if(arg instanceof IndexContext) {
+            } else if (arg instanceof IndexContext) {
                 indexContext = (IndexContext) arg;
-            } else if(arg instanceof RestContext) {
+            } else if (arg instanceof RestContext) {
                 restContext = (RestContext) arg;
             }
         }
@@ -107,11 +107,11 @@ public class ExpressionStringListener extends ExpressionBaseListener {
         String name = ctx.name.getText();
 
         int index = VariableLiteral.NO_INDEX;
-        if(indexContext != null) {
+        if (indexContext != null) {
             index = indexContext.getFirst().getNumber().intValue();
         }
         VariableLiteral rest = null;
-        if(restContext != null) {
+        if (restContext != null) {
             rest = restContext.getFirst();
         }
         parserContexts.peek().add(new VariableLiteral(name, argsContext, index, rest));
@@ -288,7 +288,7 @@ public class ExpressionStringListener extends ExpressionBaseListener {
     /////////////////////////////////////////////////////////////////////////////////////////
 
     private UnaryTerm getUnaryTerm(String op, List<Term> terms) {
-        if(terms.size() != 1) {
+        if (terms.size() != 1) {
             throw new RuntimeException(op + " should be a unary operation");
         }
         Term a = terms.get(0);
@@ -296,7 +296,7 @@ public class ExpressionStringListener extends ExpressionBaseListener {
     }
 
     private BinaryTerm getBinaryTerm(String op, List<Term> terms) {
-        if(terms.size() != 2) {
+        if (terms.size() != 2) {
             throw new RuntimeException(op + " should be a binary operation");
         }
         Term a = terms.get(0);
@@ -305,7 +305,7 @@ public class ExpressionStringListener extends ExpressionBaseListener {
     }
 
     private TernaryTerm getTernaryTerm(String op, List<Term> terms) {
-        if(terms.size() != 3) {
+        if (terms.size() != 3) {
             throw new RuntimeException(op + " should be a ternary operation");
         }
         Term a = terms.get(0);
@@ -315,7 +315,7 @@ public class ExpressionStringListener extends ExpressionBaseListener {
     }
 
     static class ArgsContext extends LinkedList<Term> implements Term {
-        public ArgsContext(Collection c) {
+        ArgsContext(Collection c) {
             super(c);
         }
 
@@ -324,8 +324,9 @@ public class ExpressionStringListener extends ExpressionBaseListener {
             return false;
         }
     }
+
     static class IndexContext extends LinkedList<NumericLiteral> implements Term {
-        public IndexContext(Collection c) {
+        IndexContext(Collection c) {
             super(c);
         }
 
@@ -334,8 +335,9 @@ public class ExpressionStringListener extends ExpressionBaseListener {
             return false;
         }
     }
+
     static class RestContext extends LinkedList<VariableLiteral> implements Term {
-        public RestContext(Collection c) {
+        RestContext(Collection c) {
             super(c);
         }
 
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParser.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParser.java
index 76c131d..7b9f124 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParser.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParser.java
@@ -21,7 +21,6 @@ package org.apache.plc4x.plugins.codegenerator.language.mspec.expression;
 
 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.plugins.codegenerator.types.terms.Term;
 
@@ -31,18 +30,15 @@ import java.io.InputStream;
 public class ExpressionStringParser {
 
     public Term parse(InputStream source) {
+        ExpressionLexer lexer;
         try {
-            ExpressionLexer lexer = new ExpressionLexer(CharStreams.fromStream(source));
-            CommonTokenStream tokens = new CommonTokenStream(lexer);
-            ExpressionParser parser = new ExpressionParser(tokens);
-            ParseTree tree = parser.expressionString();
-            ParseTreeWalker walker = new ParseTreeWalker();
-            ExpressionStringListener listener = new ExpressionStringListener();
-            walker.walk(listener, tree);
-            return listener.getRoot();
+            lexer = new ExpressionLexer(CharStreams.fromStream(source));
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
+        ExpressionStringListener listener = new ExpressionStringListener();
+        new ParseTreeWalker().walk(listener, new ExpressionParser(new CommonTokenStream(lexer)).expressionString());
+        return listener.getRoot();
     }
 
 }
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultComplexTypeDefinition.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultComplexTypeDefinition.java
index 4dbf73d..39d87f4 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultComplexTypeDefinition.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultComplexTypeDefinition.java
@@ -74,8 +74,8 @@ public class DefaultComplexTypeDefinition extends DefaultTypeDefinition implemen
     @Override
     public List<PropertyField> getAllPropertyFields() {
         List<PropertyField> fields = new LinkedList<>();
-        if(getParentType() != null) {
-            fields.addAll(((ComplexTypeDefinition)getParentType()).getAllPropertyFields());
+        if (getParentType() != null) {
+            fields.addAll(((ComplexTypeDefinition) getParentType()).getAllPropertyFields());
         }
         fields.addAll(getPropertyFields());
         return fields;
@@ -83,8 +83,8 @@ public class DefaultComplexTypeDefinition extends DefaultTypeDefinition implemen
 
     @Override
     public List<PropertyField> getParentPropertyFields() {
-        if(getParentType() != null) {
-            return ((ComplexTypeDefinition)getParentType()).getAllPropertyFields();
+        if (getParentType() != null) {
+            return ((ComplexTypeDefinition) getParentType()).getAllPropertyFields();
         }
         return Collections.emptyList();
     }
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultDiscriminatedComplexTypeDefinition.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultDiscriminatedComplexTypeDefinition.java
index 65aac2b..8d64b08 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultDiscriminatedComplexTypeDefinition.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultDiscriminatedComplexTypeDefinition.java
@@ -40,7 +40,7 @@ public class DefaultDiscriminatedComplexTypeDefinition extends DefaultComplexTyp
         // which is always a DefaultComplexTypeDefinition instance.
         return ((DefaultComplexTypeDefinition) getParentType()).getFields().stream().filter(
             field -> field instanceof DiscriminatorField).map(
-                field -> (DiscriminatorField) field).findFirst().orElse(null);
+            field -> (DiscriminatorField) field).findFirst().orElse(null);
     }
 
     public String[] getDiscriminatorValues() {
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultEnumTypeDefinition.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultEnumTypeDefinition.java
index b81136c..67d0d60 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultEnumTypeDefinition.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultEnumTypeDefinition.java
@@ -39,7 +39,7 @@ public class DefaultEnumTypeDefinition extends DefaultTypeDefinition implements
         this.type = type;
         this.enumValues = enumValues;
         this.constants = new HashMap<>();
-        if(constants != null) {
+        if (constants != null) {
             for (Argument constant : constants) {
                 this.constants.put(constant.getName(), constant.getType());
             }
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
index 42c3ce3..57214a5 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
@@ -76,7 +76,7 @@ public class MessageFormatListener extends MSpecBaseListener {
 
     @Override
     public void enterComplexType(MSpecParser.ComplexTypeContext ctx) {
-        if(ctx.enumValues != null) {
+        if (ctx.enumValues != null) {
             List<EnumValue> enumContext = new LinkedList<>();
             enumContexts.push(enumContext);
         } else {
@@ -89,11 +89,11 @@ public class MessageFormatListener extends MSpecBaseListener {
     public void exitComplexType(MSpecParser.ComplexTypeContext ctx) {
         String typeName = ctx.name.id.getText();
         Argument[] parserArguments = null;
-        if(ctx.params != null) {
+        if (ctx.params != null) {
             parserArguments = getParserArguments(ctx.params.argument());
         }
 
-        if(ctx.enumValues != null) {
+        if (ctx.enumValues != null) {
             TypeReference type = getTypeReference(ctx.type);
             EnumValue[] enumValues = getEnumValues();
             DefaultEnumTypeDefinition enumType = new DefaultEnumTypeDefinition(typeName, type, enumValues,
@@ -126,10 +126,10 @@ public class MessageFormatListener extends MSpecBaseListener {
         String name = ctx.name.id.getText();
         ArrayField.LoopType loopType = ArrayField.LoopType.valueOf(ctx.loopType.getText().toUpperCase());
         String loopExpressionString = ctx.loopExpression.expr.getText();
-        Term loopExpression =  getExpressionTerm(loopExpressionString);
+        Term loopExpression = getExpressionTerm(loopExpressionString);
         Term[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
         Field field = new DefaultArrayField(null, type, name, loopType, loopExpression, params);
-        if(parserContexts.peek() != null) {
+        if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
     }
@@ -141,7 +141,7 @@ public class MessageFormatListener extends MSpecBaseListener {
         String checksumExpressionString = ctx.checksumExpression.expr.getText();
         Term checksumExpression = getExpressionTerm(checksumExpressionString);
         Field field = new DefaultChecksumField(null, type, name, checksumExpression);
-        if(parserContexts.peek() != null) {
+        if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
     }
@@ -152,7 +152,7 @@ public class MessageFormatListener extends MSpecBaseListener {
         String name = ctx.name.id.getText();
         String expected = ctx.expected.expr.getText();
         Field field = new DefaultConstField(null, type, name, expected);
-        if(parserContexts.peek() != null) {
+        if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
     }
@@ -162,7 +162,7 @@ public class MessageFormatListener extends MSpecBaseListener {
         SimpleTypeReference type = getSimpleTypeReference(ctx.type);
         String name = ctx.name.id.getText();
         Field field = new DefaultDiscriminatorField(null, type, name);
-        if(parserContexts.peek() != null) {
+        if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
     }
@@ -173,7 +173,7 @@ public class MessageFormatListener extends MSpecBaseListener {
         String name = ctx.name.id.getText();
         Term[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
         Field field = new DefaultEnumField(null, type, name, params);
-        if(parserContexts.peek() != null) {
+        if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
     }
@@ -185,7 +185,7 @@ public class MessageFormatListener extends MSpecBaseListener {
         String serializationExpressionString = ctx.serializationExpression.expr.getText();
         Term serializationExpression = getExpressionTerm(serializationExpressionString);
         Field field = new DefaultImplicitField(null, type, name, serializationExpression);
-        if(parserContexts.peek() != null) {
+        if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
     }
@@ -197,17 +197,17 @@ public class MessageFormatListener extends MSpecBaseListener {
         ManualArrayField.LoopType loopType = ManualArrayField.LoopType.valueOf(
             ctx.loopType.getText().toUpperCase());
         String loopExpressionString = ctx.loopExpression.expr.getText();
-        Term loopExpression =  getExpressionTerm(loopExpressionString);
+        Term loopExpression = getExpressionTerm(loopExpressionString);
         String serializationExpressionString = ctx.serializationExpression.expr.getText();
         Term serializationExpression = getExpressionTerm(serializationExpressionString);
         String deserializationExpressionString = ctx.deserializationExpression.expr.getText();
         Term deserializationExpression = getExpressionTerm(deserializationExpressionString);
         String lengthExpressionString = ctx.lengthExpression.expr.getText();
-        Term lengthExpression =  getExpressionTerm(lengthExpressionString);
+        Term lengthExpression = getExpressionTerm(lengthExpressionString);
         Term[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
         Field field = new DefaultManualArrayField(null, type, name, loopType, loopExpression, serializationExpression,
             deserializationExpression, lengthExpression, params);
-        if(parserContexts.peek() != null) {
+        if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
     }
@@ -221,11 +221,11 @@ public class MessageFormatListener extends MSpecBaseListener {
         String deserializationExpressionString = ctx.deserializationExpression.expr.getText();
         Term deserializationExpression = getExpressionTerm(deserializationExpressionString);
         String lengthExpressionString = ctx.lengthExpression.expr.getText();
-        Term lengthExpression =  getExpressionTerm(lengthExpressionString);
+        Term lengthExpression = getExpressionTerm(lengthExpressionString);
         Term[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
         Field field = new DefaultManualField(null, type, name, serializationExpression, deserializationExpression,
             lengthExpression, params);
-        if(parserContexts.peek() != null) {
+        if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
     }
@@ -238,7 +238,7 @@ public class MessageFormatListener extends MSpecBaseListener {
         Term conditionExpression = getExpressionTerm(conditionExpressionString);
         Term[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
         Field field = new DefaultOptionalField(null, type, name, conditionExpression, params);
-        if(parserContexts.peek() != null) {
+        if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
     }
@@ -253,7 +253,7 @@ public class MessageFormatListener extends MSpecBaseListener {
         Term paddingCondition = getExpressionTerm(paddingConditionString);
         Term[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
         Field field = new DefaultPaddingField(null, type, name, paddingValue, paddingCondition, params);
-        if(parserContexts.peek() != null) {
+        if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
     }
@@ -263,7 +263,7 @@ public class MessageFormatListener extends MSpecBaseListener {
         SimpleTypeReference type = getSimpleTypeReference(ctx.type);
         String expected = ctx.expected.expr.getText();
         Field field = new DefaultReservedField(null, type, expected);
-        if(parserContexts.peek() != null) {
+        if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
     }
@@ -274,7 +274,7 @@ public class MessageFormatListener extends MSpecBaseListener {
         String name = ctx.name.id.getText();
         Term[] params = getFieldParams((MSpecParser.FieldDefinitionContext) ctx.parent.parent);
         Field field = new DefaultSimpleField(null, type, name, params);
-        if(parserContexts.peek() != null) {
+        if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
     }
@@ -283,11 +283,11 @@ public class MessageFormatListener extends MSpecBaseListener {
     public void enterTypeSwitchField(MSpecParser.TypeSwitchFieldContext ctx) {
         int numDiscriminators = ctx.discriminators.expression().size();
         String[] discriminatorNames = new String[numDiscriminators];
-        for(int i = 0; i < numDiscriminators; i++) {
+        for (int i = 0; i < numDiscriminators; i++) {
             discriminatorNames[i] = ctx.discriminators.expression().get(i).expr.getText();
         }
         DefaultSwitchField field = new DefaultSwitchField(discriminatorNames);
-        if(parserContexts.peek() != null) {
+        if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
     }
@@ -299,7 +299,7 @@ public class MessageFormatListener extends MSpecBaseListener {
         String valueExpressionString = ctx.valueExpression.expr.getText();
         Term valueExpression = getExpressionTerm(valueExpressionString);
         Field field = new DefaultVirtualField(null, type, name, valueExpression);
-        if(parserContexts.peek() != null) {
+        if (parserContexts.peek() != null) {
             parserContexts.peek().add(field);
         }
     }
@@ -315,17 +315,17 @@ public class MessageFormatListener extends MSpecBaseListener {
         String typeName = ctx.name.getText();
         List<Argument> parserArguments = new LinkedList<>();
         // Add all the arguments from the parent type.
-        if(((MSpecParser.ComplexTypeContext) ctx.parent.parent.parent.parent).params != null) {
+        if (((MSpecParser.ComplexTypeContext) ctx.parent.parent.parent.parent).params != null) {
             parserArguments.addAll(Arrays.asList(getParserArguments(
                 ((MSpecParser.ComplexTypeContext) ctx.parent.parent.parent.parent).params.argument())));
         }
         // Add all eventually existing local arguments.
-        if(ctx.argumentList() != null) {
+        if (ctx.argumentList() != null) {
             parserArguments.addAll(Arrays.asList(getParserArguments(ctx.argumentList().argument())));
         }
 
         String[] discriminatorValues;
-        if(ctx.discriminatorValues != null) {
+        if (ctx.discriminatorValues != null) {
             List<MSpecParser.ExpressionContext> expressions = ctx.discriminatorValues.expression();
             discriminatorValues = new String[expressions.size()];
             for (int i = 0; i < expressions.size(); i++) {
@@ -340,7 +340,7 @@ public class MessageFormatListener extends MSpecBaseListener {
 
         // Add the type to the switch field definition.
         DefaultSwitchField switchField = getSwitchField();
-        if(switchField == null) {
+        if (switchField == null) {
             throw new RuntimeException("This shouldn't have happened");
         }
         switchField.addCase(type);
@@ -354,12 +354,12 @@ public class MessageFormatListener extends MSpecBaseListener {
         String value = unquoteString(ctx.valueExpression.getText());
         String name = ctx.name.getText();
         Map<String, String> constants = null;
-        if(ctx.constantValueExpressions != null) {
+        if (ctx.constantValueExpressions != null) {
             MSpecParser.ComplexTypeContext parentCtx = (MSpecParser.ComplexTypeContext) ctx.parent;
             int numConstantValues = parentCtx.params.argument().size();
             int numExpressionValues = ctx.constantValueExpressions.expression().size();
             // This only works if we provide exactly the same number of expressions as we defined constants
-            if(numConstantValues != numExpressionValues) {
+            if (numConstantValues != numExpressionValues) {
                 throw new RuntimeException("Number of constant value expressions doesn't match the number of " +
                     "defined constants. Expecting " + numConstantValues + " but got " + numExpressionValues);
             }
@@ -390,10 +390,10 @@ public class MessageFormatListener extends MSpecBaseListener {
     }
 
     private TypeReference getTypeReference(MSpecParser.TypeReferenceContext ctx) {
-        if(ctx.simpleTypeReference != null) {
+        if (ctx.simpleTypeReference != null) {
             SimpleTypeReference.SimpleBaseType simpleBaseType = SimpleTypeReference.SimpleBaseType.valueOf(
                 ctx.simpleTypeReference.base.getText().toUpperCase());
-            if(ctx.simpleTypeReference.size != null) {
+            if (ctx.simpleTypeReference.size != null) {
                 int size = Integer.parseInt(ctx.simpleTypeReference.size.getText());
                 return new DefaultSimpleTypeReference(simpleBaseType, size);
             } else {
@@ -407,7 +407,7 @@ public class MessageFormatListener extends MSpecBaseListener {
     private SimpleTypeReference getSimpleTypeReference(MSpecParser.DataTypeContext ctx) {
         SimpleTypeReference.SimpleBaseType simpleBaseType =
             SimpleTypeReference.SimpleBaseType.valueOf(ctx.base.getText().toUpperCase());
-        if(ctx.size != null) {
+        if (ctx.size != null) {
             int size = Integer.parseInt(ctx.size.getText());
             return new DefaultSimpleTypeReference(simpleBaseType, size);
         } else {
@@ -417,7 +417,7 @@ public class MessageFormatListener extends MSpecBaseListener {
 
     private DefaultSwitchField getSwitchField() {
         for (Field field : Objects.requireNonNull(parserContexts.peek())) {
-            if(field instanceof DefaultSwitchField) {
+            if (field instanceof DefaultSwitchField) {
                 return (DefaultSwitchField) field;
             }
         }
@@ -440,9 +440,9 @@ public class MessageFormatListener extends MSpecBaseListener {
 
     private Term[] getFieldParams(MSpecParser.FieldDefinitionContext parentCtx) {
         Term[] params = null;
-        if(parentCtx.params != null) {
+        if (parentCtx.params != null) {
             params = new Term[parentCtx.params.expression().size()];
-            for(int i = 0; i < parentCtx.params.expression().size(); i++) {
+            for (int i = 0; i < parentCtx.params.expression().size(); i++) {
                 params[i] = parseExpression(parentCtx.params.expression().get(i).expr.getText());
             }
         }
@@ -460,7 +460,7 @@ public class MessageFormatListener extends MSpecBaseListener {
     }
 
     private String unquoteString(String quotedString) {
-        if(quotedString != null && quotedString.length() > 2) {
+        if (quotedString != null && quotedString.length() > 2) {
             return quotedString.substring(1, quotedString.length() - 1);
         }
         return quotedString;
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParser.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParser.java
index a134666..cc6f9df 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParser.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParser.java
@@ -19,10 +19,8 @@
 
 package org.apache.plc4x.plugins.codegenerator.language.mspec.parser;
 
-import org.antlr.v4.runtime.CharStream;
 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.plugins.codegenerator.language.mspec.MSpecLexer;
 import org.apache.plc4x.plugins.codegenerator.language.mspec.MSpecParser;
@@ -31,55 +29,18 @@ import org.apache.plc4x.plugins.codegenerator.types.definitions.TypeDefinition;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Map;
-import java.util.function.Function;
-import java.util.function.Supplier;
 
 public class MessageFormatParser {
 
-    // TODO: can be used a instance once thread safety is asserted
-    private Function<CharStream, MSpecLexer> lexerBuilder;
-
-    // TODO: can be used a instance once thread safety is asserted
-    private Function<MSpecLexer, CommonTokenStream> commonTokenStreamBuilder;
-
-    // TODO: can be used a instance once thread safety is asserted
-    private Function<CommonTokenStream, MSpecParser> commonTokenStreamMSpecParserBuilder;
-
-    // TODO: can be used a instance once thread safety is asserted
-    private Supplier<ParseTreeWalker> voidParseTreeWalkerBuilder;
-
-    // TODO: can be used a instance once thread safety is asserted
-    private Supplier<MessageFormatListener> messageFormatListenerBuilder;
-
-    public MessageFormatParser() {
-        lexerBuilder = MSpecLexer::new;
-        commonTokenStreamBuilder = CommonTokenStream::new;
-        commonTokenStreamMSpecParserBuilder = MSpecParser::new;
-        voidParseTreeWalkerBuilder = ParseTreeWalker::new;
-        messageFormatListenerBuilder = MessageFormatListener::new;
-    }
-
-    MessageFormatParser(Function<CharStream, MSpecLexer> lexerBuilder, Function<MSpecLexer, CommonTokenStream> commonTokenStreamBuilder, Function<CommonTokenStream, MSpecParser> commonTokenStreamMSpecParserBuilder, Supplier<ParseTreeWalker> voidParseTreeWalkerBuilder, Supplier<MessageFormatListener> messageFormatListenerBuilder) {
-        this.lexerBuilder = lexerBuilder;
-        this.commonTokenStreamBuilder = commonTokenStreamBuilder;
-        this.commonTokenStreamMSpecParserBuilder = commonTokenStreamMSpecParserBuilder;
-        this.voidParseTreeWalkerBuilder = voidParseTreeWalkerBuilder;
-        this.messageFormatListenerBuilder = messageFormatListenerBuilder;
-    }
-
     public Map<String, TypeDefinition> parse(InputStream source) {
         MSpecLexer lexer;
         try {
-            lexer = lexerBuilder.apply(CharStreams.fromStream(source));
+            lexer = new MSpecLexer(CharStreams.fromStream(source));
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
-        CommonTokenStream tokens = commonTokenStreamBuilder.apply(lexer);
-        MSpecParser parser = commonTokenStreamMSpecParserBuilder.apply(tokens);
-        ParseTree tree = parser.file();
-        ParseTreeWalker walker = voidParseTreeWalkerBuilder.get();
-        MessageFormatListener listener = messageFormatListenerBuilder.get();
-        walker.walk(listener, tree);
+        MessageFormatListener listener = new MessageFormatListener();
+        new ParseTreeWalker().walk(listener, new MSpecParser(new CommonTokenStream(lexer)).file());
         return listener.getTypes();
     }
 
diff --git a/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListenerTest.java b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListenerTest.java
deleted file mode 100644
index 3d9f4c4..0000000
--- a/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListenerTest.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- 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.
- */
-
-package org.apache.plc4x.plugins.codegenerator.language.mspec.parser;
-
-import org.antlr.v4.runtime.CommonToken;
-import org.apache.plc4x.plugins.codegenerator.language.mspec.MSpecParser;
-import org.apache.plc4x.plugins.codegenerator.types.definitions.TypeDefinition;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.junit.jupiter.MockitoExtension;
-
-import java.util.Map;
-
-import static org.hamcrest.CoreMatchers.not;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.hasSize;
-
-// TODO: implement me
-@ExtendWith(MockitoExtension.class)
-class MessageFormatListenerTest {
-
-    MessageFormatListener SUT;
-
-    @BeforeEach
-    void setUp() {
-        SUT = new MessageFormatListener();
-    }
-
-    @Test
-    void getTypes() {
-        Map<String, TypeDefinition> types = SUT.getTypes();
-        assertThat(types, nullValue());
-    }
-
-    @Test
-    void enterFile() {
-        assertThat(SUT.getParserContexts(), nullValue());
-        assertThat(SUT.getEnumContexts(), nullValue());
-        assertThat(SUT.getTypes(), nullValue());
-        SUT.enterFile(null);
-        assertThat(SUT.getParserContexts(), not(nullValue()));
-        assertThat(SUT.getEnumContexts(), not(nullValue()));
-        assertThat(SUT.getTypes(), not(nullValue()));
-    }
-
-    @Test
-    void enterComplexType() {
-        assertThat(SUT.getParserContexts(), nullValue());
-        assertThat(SUT.getEnumContexts(), nullValue());
-        assertThat(SUT.getTypes(), nullValue());
-        SUT.enterFile(null);
-        MSpecParser.ComplexTypeContext complexTypeContext = new MSpecParser.ComplexTypeContext(null, 0);
-        SUT.enterComplexType(complexTypeContext);
-        assertThat(SUT.getParserContexts(), hasSize(1));
-        assertThat(SUT.getEnumContexts(), hasSize(0));
-        assertThat(SUT.getTypes().values(), hasSize(0));
-        complexTypeContext.enumValues = new MSpecParser.EnumValueDefinitionContext(null, 0);
-        SUT.enterComplexType(complexTypeContext);
-        assertThat(SUT.getParserContexts(), hasSize(1));
-        assertThat(SUT.getEnumContexts(), hasSize(1));
-        assertThat(SUT.getTypes().values(), hasSize(0));
-    }
-
-    @Test
-    void exitComplexType() {
-        MSpecParser.ComplexTypeContext complexTypeContext = new MSpecParser.ComplexTypeContext(null, 0);
-        complexTypeContext.name = new MSpecParser.IdExpressionContext(null, 0);
-        complexTypeContext.name.id = new CommonToken(0);
-        SUT.exitComplexType(complexTypeContext);
-    }
-
-    @Test
-    void enterArrayField() {
-    }
-
-    @Test
-    void enterChecksumField() {
-    }
-
-    @Test
-    void enterConstField() {
-    }
-
-    @Test
-    void enterDiscriminatorField() {
-    }
-
-    @Test
-    void enterEnumField() {
-    }
-
-    @Test
-    void enterImplicitField() {
-    }
-
-    @Test
-    void enterManualArrayField() {
-    }
-
-    @Test
-    void enterManualField() {
-    }
-
-    @Test
-    void enterOptionalField() {
-    }
-
-    @Test
-    void enterPaddingField() {
-    }
-
-    @Test
-    void enterReservedField() {
-    }
-
-    @Test
-    void enterSimpleField() {
-    }
-
-    @Test
-    void enterTypeSwitchField() {
-    }
-
-    @Test
-    void enterVirtualField() {
-    }
-
-    @Test
-    void enterCaseStatement() {
-    }
-
-    @Test
-    void exitCaseStatement() {
-    }
-
-    @Test
-    void enterEnumValueDefinition() {
-    }
-
-    @Test
-    void main() {
-    }
-}
\ No newline at end of file
diff --git a/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParserTest.java b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParserTest.java
index 7aa47d2..37b9720 100644
--- a/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParserTest.java
+++ b/build-utils/protocol-base-mspec/src/test/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParserTest.java
@@ -19,56 +19,18 @@
 
 package org.apache.plc4x.plugins.codegenerator.language.mspec.parser;
 
-import org.antlr.v4.runtime.CommonTokenStream;
-import org.antlr.v4.runtime.tree.ParseTreeWalker;
 import org.apache.commons.io.IOUtils;
-import org.apache.plc4x.plugins.codegenerator.language.mspec.MSpecLexer;
-import org.apache.plc4x.plugins.codegenerator.language.mspec.MSpecParser;
-import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
 
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 
 import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.Mockito.mock;
 
-// TODO: implement me
-@ExtendWith(MockitoExtension.class)
 class MessageFormatParserTest {
 
-    //@InjectMocks
-    MessageFormatParser SUT;
-
-    @Mock
-    MSpecLexer mSpecLexer;
-
-    @Mock
-    CommonTokenStream commonTokenStream;
-
-    @Mock
-    MSpecParser mSpecParser;
-
-    @Mock
-    ParseTreeWalker parseTreeWalker;
-
-    @Mock
-    MessageFormatListener messageFormatListener;
-
-    @BeforeEach
-    void setUp() {
-        SUT = new MessageFormatParser(
-            (_ignore) -> mSpecLexer,
-            (_ignore) -> commonTokenStream,
-            (_ignore) -> mSpecParser,
-            () -> parseTreeWalker,
-            () -> messageFormatListener
-        );
-    }
+    MessageFormatParser SUT = new MessageFormatParser();
 
     @Test
     void parseNull() {
@@ -78,10 +40,6 @@ class MessageFormatParserTest {
     @Disabled("mockito broken because of NPE in REAL code")
     @Test
     void parseSomething() {
-        // TODO: seems like mockito is broken somehow...
-        MSpecParser mSpecParser = mock(MSpecParser.class);
-        // TODO: ... because this throws a NPE... (somehow call ends up in real code)
-        mSpecParser.file();
         InputStream is = IOUtils.toInputStream("test", StandardCharsets.UTF_8);
         SUT.parse(is);
     }