You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2021/10/20 19:49:38 UTC

[plc4x] branch feature/mspec-ng updated: - Continued implementing optional, virtual, ... fields.

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

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


The following commit(s) were added to refs/heads/feature/mspec-ng by this push:
     new e4d93c4  - Continued implementing optional, virtual, ... fields.
e4d93c4 is described below

commit e4d93c45aeb6996b7faf35f13c01f16f3a1e4b52
Author: cdutz <ch...@c-ware.de>
AuthorDate: Wed Oct 20 21:49:28 2021 +0200

    - Continued implementing optional, virtual, ... fields.
---
 .../language/java/JavaLanguageTemplateHelper.java  | 17 ++++-
 .../resources/templates/java/io-template.java.ftlh | 76 +++-------------------
 .../spi/codegen/fields/FieldReaderFactory.java     |  8 +++
 .../spi/codegen/fields/FieldReaderVirtual.java     |  9 ++-
 ...ReaderComplex.java => ComplexTypeSupplier.java} |  7 +-
 .../java/spi/codegen/io/DataReaderComplex.java     |  2 +-
 .../spi/codegen/io/DataReaderComplexDefault.java   |  7 +-
 .../java/spi/codegen/io/DataReaderEnumDefault.java |  4 +-
 .../java/spi/generation/WithReaderWriterArgs.java  |  2 +
 .../s7/src/main/resources/protocols/s7/s7.mspec    | 40 ++++++------
 10 files changed, 72 insertions(+), 100 deletions(-)

diff --git a/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java b/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
index 1a205ec..2eafd94 100644
--- a/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
+++ b/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
@@ -374,7 +374,22 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
             SimpleTypeReference simpleTypeReference = (SimpleTypeReference) typeReference;
             return getDataReaderCall(simpleTypeReference);
         } else if (typeReference.isComplexTypeReference()) {
-            return "new DataReaderComplex(readBuffer)";
+            final ComplexTypeReference complexTypeReference = typeReference.asComplexTypeReference().get();
+            String parserArguments = "";
+            if(complexTypeReference.getParams().isPresent()) {
+                final List<Term> terms = complexTypeReference.getParams().get();
+                StringBuilder sb = new StringBuilder();
+                for (Term term : terms) {
+                    sb.append(", ").append(toParseExpression(null, term, null));
+                }
+                parserArguments = sb.toString();
+            }
+            return "new DataReaderComplexDefault<>(new ComplexTypeSupplier<" + getLanguageTypeNameForTypeReference(typeReference) + ">() {" +
+                "    @Override\n" +
+                "    public " + getLanguageTypeNameForTypeReference(typeReference) + " get() throws ParseException {\n" +
+                "        return " + getLanguageTypeNameForTypeReference(typeReference) + "IO.staticParse(readBuffer" + parserArguments + ");\n" +
+                "    }" +
+                "}, readBuffer)";
         } else {
             throw new IllegalStateException("What is this type? " + typeReference);
         }
diff --git a/code-generation/language-java/src/main/resources/templates/java/io-template.java.ftlh b/code-generation/language-java/src/main/resources/templates/java/io-template.java.ftlh
index 7167fec..2232d00 100644
--- a/code-generation/language-java/src/main/resources/templates/java/io-template.java.ftlh
+++ b/code-generation/language-java/src/main/resources/templates/java/io-template.java.ftlh
@@ -444,71 +444,16 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO<
         // Manual Field (${manualField.name})
         ${helper.getLanguageTypeNameForField(field)} ${manualField.name} = (${helper.getLanguageTypeNameForField(field)}) (${helper.toParseExpression(manualField, manualField.parseExpression, parserArguments)});
         <#break>
-    <#-- TODO: Port this -->
     <#case "optional">
         <#assign optionalField = field.asOptionalField().orElseThrow()>
+        <#assign typedField = field.asTypedField().orElseThrow()>
+        <#assign namedField = field.asNamedField().orElseThrow()>
 
-        // Optional Field (${optionalField.name}) (Can be skipped, if a given expression evaluates to false)
-        ${helper.getLanguageTypeNameForField(optionalField)} ${optionalField.name} = null;
-        <#-- TODO: we need to initalize base types-->
-        curPos = readBuffer.getPos();
-        try {
+        // ${field.typeName?cap_first} Field (${namedField.name}) (Can be skipped, if a given expression evaluates to false)
         <#if optionalField.conditionExpression.present && optionalField.conditionExpression.orElseThrow().contains("curPos")>
-        curPos = readBuffer.getPos();
-        </#if>
-        <#if optionalField.conditionExpression.present>
-        if(${helper.toParseExpression(optionalField, optionalField.conditionExpression.get(), parserArguments)}) {
+            curPos = readBuffer.getPos();
         </#if>
-        <@compress single_line=true>
-            ${optionalField.name} =
-            <#if helper.isEnumField(optionalField)>
-             ${helper.getLanguageTypeNameForField(optionalField)}.enumForValue(
-                ${helper.getReadBufferReadMethodCall(optionalField.name, helper.getEnumBaseTypeReference(optionalField.type), "", optionalField)}
-            )
-            <#elseif helper.isComplexTypeReference(optionalField.type)>
-                <#assign complexTypeReference=optionalField.type.asComplexTypeReference().orElseThrow()>
-                <#assign typeName=complexTypeReference.name>
-                <#assign typeDefinition=helper.getTypeDefinitionForTypeReference(complexTypeReference)>
-                <#if typeDefinition.isDiscriminatedChildTypeDefinition()>
-                    <#-- Usually you don't use child directly unless they are parameterized #-->
-                    <#assign typeName=typeDefinition.parentType.name>
-                    <#assign typeDefinition=typeDefinition.parentType>
-                </#if>
-                <#-- We downcast to the referenced type-->
-            (${complexTypeReference.name}) ${typeName}IO.staticParse(
-                readBuffer
-                <#if field.params.isPresent()>,
-                    <#list field.params.orElseThrow() as parserArgument>
-                        (${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(optionalField.type, parserArgument?index), true)})
-                        (${helper.toParseExpression(optionalField, parserArgument, parserArguments)})<#sep>, </#sep>
-                    </#list>
-                </#if>
-                <#if complexTypeReference.params.isPresent() && typeDefinition.parserArguments.isPresent()>
-                    <#assign argumentOffset=0>
-                    <#if field.params.isPresent()><#assign argumentOffset=field.params.orElseThrow()?size></#if>
-                    ,
-                    <#list complexTypeReference.params.orElseThrow() as typeParam>
-                    <#-- We cast here explicitly as java sometimes can't infer the type. e.g. 0 is a int and not a byte#-->
-                        (${helper.getLanguageTypeNameForTypeReference(typeDefinition.parserArguments.orElseThrow()[typeParam?index + argumentOffset].type, true)})
-                        ${helper.toAccessExpression(null, typeParam, null)}<#sep>, </#sep>
-                    </#list>
-                </#if>
-                )
-            <#else>
-             ${helper.getReadBufferReadMethodCall(optionalField.name, optionalField.type.asSimpleTypeReference().orElseThrow(), "", optionalField)}
-            </#if>
-            ;
-        </...@compress>
-
-        <#if optionalField.conditionExpression.present>
-        }
-        </#if>
-            if (1 == 2) {
-                throw new ParseAssertException("oh no java");
-            }
-        } catch(ParseAssertException ignore){
-            readBuffer.reset(curPos);
-        }
+        ${helper.getLanguageTypeNameForField(field)} ${namedField.name} = read${field.typeName?cap_first}Field("${namedField.name}", ${helper.getDataReaderCall(typedField.type)}, <#if optionalField.conditionExpression.present>${helper.toParseExpression(optionalField, optionalField.conditionExpression.get(), parserArguments)}<#else>true</#if>);
         <#break>
     <#case "assert">
         <#assign assertField = field.asAssertField().orElseThrow()>
@@ -647,16 +592,13 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO<
         // ${field.typeName?cap_first} Field
         read${field.typeName?cap_first}Field("unknown", ${helper.getDataReaderCall(typedField.type)});
         <#break>
-    <#-- TODO: Port this -->
     <#case "virtual">
         <#assign virtualField = field.asVirtualField().orElseThrow()>
+        <#assign typedField = field.asTypedField().orElseThrow()>
+        <#assign namedField = field.asNamedField().orElseThrow()>
 
-        // Virtual field (Just declare a local variable so we can access it in the parser)
-        <#if helper.getLanguageTypeNameForField(field) = 'String'>
-        ${helper.getLanguageTypeNameForField(field)} ${virtualField.name} = ${helper.getLanguageTypeNameForField(field)}.valueOf(${helper.toParseExpression(virtualField, virtualField.valueExpression, parserArguments)});
-        <#else>
-        ${helper.getLanguageTypeNameForField(field)} ${virtualField.name} = (${helper.getLanguageTypeNameForField(field)}) (${helper.toParseExpression(virtualField, virtualField.valueExpression, parserArguments)});
-        </#if>
+        // ${field.typeName?cap_first} Field (${namedField.name})
+        ${helper.getLanguageTypeNameForField(field)} ${namedField.name} = read${field.typeName?cap_first}Field(${helper.getLanguageTypeNameForField(field)}.class, ${helper.toParseExpression(virtualField, virtualField.valueExpression, parserArguments)});
         <#break>
 </#switch>
 </#list>
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldReaderFactory.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldReaderFactory.java
index f81a75d..9dc32dc 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldReaderFactory.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldReaderFactory.java
@@ -52,6 +52,10 @@ public class FieldReaderFactory {
         return new FieldReaderImplicit<T>().readField(logicalName, dataReader, readerArgs);
     }
 
+    public static <T> T readOptionalField(String logicalName, DataReader<T> dataReader, boolean condition, WithReaderArgs... readerArgs) throws ParseException {
+        return new FieldReaderOptional<T>().readOptionalField(logicalName, dataReader, condition, readerArgs);
+    }
+
     public static <T> void readPaddingField(DataReader<T> dataReader, int timesPadding, WithReaderArgs... readerArgs) throws ParseException {
         new FieldReaderPadding<T>().readPaddingField(dataReader, timesPadding, readerArgs);
     }
@@ -64,4 +68,8 @@ public class FieldReaderFactory {
         return new FieldReaderUnknown<T>().readUnknownField(logicalName, dataReader, readerArgs);
     }
 
+    public static <T> T readVirtualField(Class<T> type, Object valueExpression, WithReaderArgs... readerArgs) throws ParseException {
+        return new FieldReaderVirtual<T>().readVirtualField(type, valueExpression, readerArgs);
+    }
+
 }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldReaderVirtual.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldReaderVirtual.java
index 61a8b21..375c515 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldReaderVirtual.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldReaderVirtual.java
@@ -30,7 +30,14 @@ public class FieldReaderVirtual<T> implements FieldReader<T> {
 
     @Override
     public T readField(String logicalName, DataReader<T> dataReader, WithReaderArgs... readerArgs) throws ParseException {
-        return switchByteOrderIfNecessary(() -> dataReader.read(logicalName, readerArgs), dataReader, extractByteOder(readerArgs).orElse(null));
+        throw new IllegalStateException("not possible with unknown field");
+    }
+
+    public T readVirtualField(Class<T> type, Object valueExpression, WithReaderArgs... readerArgs) throws ParseException {
+        if(type == String.class) {
+            return (T) String.valueOf(valueExpression);
+        }
+        return (T) valueExpression;
     }
 
 }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataReaderComplex.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/ComplexTypeSupplier.java
similarity index 77%
copy from plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataReaderComplex.java
copy to plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/ComplexTypeSupplier.java
index 662ef53..2ad9d4d 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataReaderComplex.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/ComplexTypeSupplier.java
@@ -19,12 +19,9 @@
 package org.apache.plc4x.java.spi.codegen.io;
 
 import org.apache.plc4x.java.spi.generation.ParseException;
-import org.apache.plc4x.java.spi.generation.WithReaderArgs;
 
-import java.util.function.Supplier;
+public interface ComplexTypeSupplier<T> {
 
-public interface DataReaderComplex<T> extends DataReader<T> {
-
-    T read(String logicalName, Supplier<T> complexSupplier, WithReaderArgs... readerArgs) throws ParseException;
+    T get() throws ParseException;
 
 }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataReaderComplex.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataReaderComplex.java
index 662ef53..41b18d2 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataReaderComplex.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataReaderComplex.java
@@ -25,6 +25,6 @@ import java.util.function.Supplier;
 
 public interface DataReaderComplex<T> extends DataReader<T> {
 
-    T read(String logicalName, Supplier<T> complexSupplier, WithReaderArgs... readerArgs) throws ParseException;
+    T read(String logicalName, ComplexTypeSupplier<T> complexSupplier, WithReaderArgs... readerArgs) throws ParseException;
 
 }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataReaderComplexDefault.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataReaderComplexDefault.java
index 91944f7..ee60319 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataReaderComplexDefault.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataReaderComplexDefault.java
@@ -26,12 +26,13 @@ import org.apache.plc4x.java.spi.generation.WithReaderArgs;
 import java.util.function.Supplier;
 
 public class DataReaderComplexDefault<T> implements DataReaderComplex<T> {
-    private final Supplier<T> complexSupplier;
+
+    private final ComplexTypeSupplier<T> complexSupplier;
 
     // TODO: maybe replace with resetable or something so its clear that that's the only purpose
     private final ReadBuffer readBuffer;
 
-    public DataReaderComplexDefault(Supplier<T> complexSupplier, ReadBuffer readBuffer) {
+    public DataReaderComplexDefault(ComplexTypeSupplier<T> complexSupplier, ReadBuffer readBuffer) {
         this.complexSupplier = complexSupplier;
         this.readBuffer = readBuffer;
     }
@@ -61,7 +62,7 @@ public class DataReaderComplexDefault<T> implements DataReaderComplex<T> {
         return read(logicalName, complexSupplier, readerArgs);
     }
 
-    public T read(String logicalName, Supplier<T> complexSupplier, WithReaderArgs... readerArgs) throws ParseException {
+    public T read(String logicalName, ComplexTypeSupplier<T> complexSupplier, WithReaderArgs... readerArgs) throws ParseException {
         readBuffer.pullContext(logicalName,readerArgs);
         final T t = complexSupplier.get();
         readBuffer.closeContext(logicalName,readerArgs);
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataReaderEnumDefault.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataReaderEnumDefault.java
index fc7b398..e3f758e 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataReaderEnumDefault.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataReaderEnumDefault.java
@@ -27,9 +27,9 @@ import java.util.function.Function;
 public class DataReaderEnumDefault<T, I> implements DataReaderEnum<T> {
 
     private final Function<I, T> enumResolver;
-    private final DataReaderSimple<I> dataReader;
+    private final DataReader<I> dataReader;
 
-    public DataReaderEnumDefault(Function<I, T> enumResolver, DataReaderSimple<I> dataReader) {
+    public DataReaderEnumDefault(Function<I, T> enumResolver, DataReader<I> dataReader) {
         this.enumResolver = enumResolver;
         this.dataReader = dataReader;
     }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WithReaderWriterArgs.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WithReaderWriterArgs.java
index 9baaed2..05a25dd 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WithReaderWriterArgs.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WithReaderWriterArgs.java
@@ -19,6 +19,7 @@
 package org.apache.plc4x.java.spi.generation;
 
 public interface WithReaderWriterArgs extends WithReaderArgs, WithWriterArgs {
+
     static WithReaderWriterArgs WithRenderAsList(boolean renderAsList) {
         return (withRenderAsList) () -> renderAsList;
     }
@@ -26,6 +27,7 @@ public interface WithReaderWriterArgs extends WithReaderArgs, WithWriterArgs {
     static WithReaderWriterArgs WithAdditionalStringRepresentation(String stringRepresentation) {
         return (withAdditionalStringRepresentation) () -> stringRepresentation;
     }
+
 }
 
 interface withRenderAsList extends WithReaderWriterArgs {
diff --git a/protocols/s7/src/main/resources/protocols/s7/s7.mspec b/protocols/s7/src/main/resources/protocols/s7/s7.mspec
index 9e35fa6..4249c7b 100644
--- a/protocols/s7/src/main/resources/protocols/s7/s7.mspec
+++ b/protocols/s7/src/main/resources/protocols/s7/s7.mspec
@@ -22,10 +22,10 @@
 ////////////////////////////////////////////////////////////////
 
 [type 'TPKTPacket' byteOrder='"BIG_ENDIAN"'
-    [const    uint 8     'protocolId' '0x03']
-    [reserved uint 8     '0x00']
-    [implicit uint 16    'len'        'payload.lengthInBytes + 4']
-    [simple   COTPPacket 'payload' ['len - 4']]
+    [const    uint 8                 'protocolId' '0x03'                     ]
+    [reserved uint 8                 '0x00'                                  ]
+    [implicit uint 16                'len'        'payload.lengthInBytes + 4']
+    [simple   COTPPacket ['len - 4'] 'payload'                               ]
 ]
 
 ////////////////////////////////////////////////////////////////
@@ -37,35 +37,35 @@
     [discriminator uint 8 'tpduCode']
     [typeSwitch 'tpduCode'
         ['0xF0' COTPPacketData
-            [simple bit    'eot']
-            [simple uint 7 'tpduRef']
+            [simple bit    'eot'                            ]
+            [simple uint 7 'tpduRef'                        ]
         ]
         ['0xE0' COTPPacketConnectionRequest
             [simple uint 16           'destinationReference']
-            [simple uint 16           'sourceReference']
-            [simple COTPProtocolClass 'protocolClass']
+            [simple uint 16           'sourceReference'     ]
+            [simple COTPProtocolClass 'protocolClass'       ]
         ]
         ['0xD0' COTPPacketConnectionResponse
             [simple uint 16           'destinationReference']
-            [simple uint 16           'sourceReference']
-            [simple COTPProtocolClass 'protocolClass']
+            [simple uint 16           'sourceReference'     ]
+            [simple COTPProtocolClass 'protocolClass'       ]
         ]
         ['0x80' COTPPacketDisconnectRequest
             [simple uint 16           'destinationReference']
-            [simple uint 16           'sourceReference']
-            [simple COTPProtocolClass 'protocolClass']
+            [simple uint 16           'sourceReference'     ]
+            [simple COTPProtocolClass 'protocolClass'       ]
         ]
         ['0xC0' COTPPacketDisconnectResponse
-            [simple uint 16 'destinationReference']
-            [simple uint 16 'sourceReference']
+            [simple uint 16 'destinationReference'          ]
+            [simple uint 16 'sourceReference'               ]
         ]
         ['0x70' COTPPacketTpduError
-            [simple uint 16 'destinationReference']
-            [simple uint 8  'rejectCause']
+            [simple uint 16 'destinationReference'          ]
+            [simple uint 8  'rejectCause'                   ]
         ]
     ]
-    [array    COTPParameter 'parameters' length '(headerLength + 1) - curPos' ['(headerLength + 1) - curPos']]
-    [optional S7Message     'payload'    'curPos < cotpLen']
+    [array    COTPParameter ['(headerLength + 1) - curPos'] 'parameters' length '(headerLength + 1) - curPos']
+    [optional S7Message                                     'payload'    'curPos < cotpLen']
 ]
 
 [discriminatedType 'COTPParameter' [uint 8 'rest']
@@ -115,8 +115,8 @@
         ['0x07' S7MessageUserData
         ]
     ]
-    [optional S7Parameter 'parameter' 'parameterLength > 0' ['messageType']]
-    [optional S7Payload   'payload'   'payloadLength > 0'   ['messageType', 'parameter']]
+    [optional S7Parameter ['messageType']              'parameter' 'parameterLength > 0']
+    [optional S7Payload   ['messageType', 'parameter'] 'payload'   'payloadLength > 0'  ]
 ]
 
 ////////////////////////////////////////////////////////////////