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 2022/08/04 14:22:37 UTC

[plc4x] branch develop updated: feat(codegen/plc4j): save reserved in case they differ so they can be written out again using the same value

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

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


The following commit(s) were added to refs/heads/develop by this push:
     new 8baeacf1d feat(codegen/plc4j): save reserved in case they differ so they can be written out again using the same value
8baeacf1d is described below

commit 8baeacf1da74042dd41205cc9620b9523af37c0d
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Thu Aug 4 16:22:29 2022 +0200

    feat(codegen/plc4j): save reserved in case they differ so they can be written out again using the same value
---
 .../templates/java/complex-type-template.java.ftlh | 126 +++++++++++++++++++--
 .../src/main/resources/protocols/test/test.mspec   |  10 ++
 .../spi/codegen/fields/FieldReaderReserved.java    |   3 +-
 3 files changed, 127 insertions(+), 12 deletions(-)

diff --git a/code-generation/language-java/src/main/resources/templates/java/complex-type-template.java.ftlh b/code-generation/language-java/src/main/resources/templates/java/complex-type-template.java.ftlh
index c23bd040d..4f2a872f1 100644
--- a/code-generation/language-java/src/main/resources/templates/java/complex-type-template.java.ftlh
+++ b/code-generation/language-java/src/main/resources/templates/java/complex-type-template.java.ftlh
@@ -136,6 +136,13 @@ public<#if type.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${ty
     protected final ${helper.getLanguageTypeNameForTypeReference(parserArgument.type)} ${parserArgument.name};
     </#list>
 </#if>
+<#assign reservedFields=type.getFields()?filter(f->f.isReservedField())>
+<#if reservedFields?has_content>
+    // Reserved Fields
+    <#list reservedFields as reservedField>
+    private ${helper.getLanguageTypeNameForTypeReference(reservedField.asReservedField().orElseThrow().type, false)} reservedField${reservedField?index};
+    </#list>
+</#if>
 
     <#-- getAllPropertyFields() returns not only the property fields of this type but also of it's parents -->
     <@compress single_line=true>
@@ -235,6 +242,7 @@ public<#if type.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${ty
         <#else>
             int startPos = positionAware.getPos();
             writeBuffer.pushContext("${type.name}");
+            <#assign reservedFieldIndex=0>
             <#list type.fields as field>
                 <#switch field.typeName>
                     <#case "array">
@@ -335,7 +343,7 @@ public<#if type.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${ty
                         <#assign typedField = field.asTypedField().orElseThrow()>
 
                         // Reserved Field (reserved)
-                        writeReservedField("reserved", ${helper.getReservedValue(reservedField)}, ${helper.getDataWriterCall(typedField.type, "reserved")});
+                        writeReservedField("reserved", reservedField${reservedFieldIndex}!=null?reservedField${reservedFieldIndex}:${helper.getReservedValue(reservedField)}, ${helper.getDataWriterCall(typedField.type, "reserved")});<#assign reservedFieldIndex=reservedFieldIndex+1>
                         <#break>
                     <#case "simple">
                         <#assign simpleField = field.asSimpleField().orElseThrow()>
@@ -588,6 +596,7 @@ public<#if type.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${ty
         PositionAware positionAware = readBuffer;
         int startPos = positionAware.getPos();
         int curPos;
+    <#assign reservedFieldIndex=0>
     <#list type.fields as field>
         <#switch field.typeName>
             <#case "array">
@@ -696,7 +705,7 @@ public<#if type.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${ty
                 <#assign reservedField = field.asReservedField().orElseThrow()>
                 <#assign typedField = field.asTypedField().orElseThrow()>
 
-                read${field.typeName?cap_first}Field("reserved", ${helper.getDataReaderCall(typedField.type)}, ${helper.getReservedValue(reservedField)}${helper.getFieldOptions(typedField, parserArguments)});
+                ${helper.getLanguageTypeNameForTypeReference(reservedField.type, false)} reservedField${reservedFieldIndex}<#assign reservedFieldIndex=reservedFieldIndex+1> = read${field.typeName?cap_first}Field("reserved", ${helper.getDataReaderCall(typedField.type)}, ${helper.getReservedValue(reservedField)}${helper.getFieldOptions(typedField, parserArguments)});
                 <#break>
             <#case "simple">
                 <#assign simpleField = field.asSimpleField().orElseThrow()>
@@ -779,17 +788,69 @@ public<#if type.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${ty
     readBuffer.closeContext("${type.name}");
     // Create the instance
     <#if type.isDiscriminatedChildTypeDefinition()>
-        return new ${type.name}Builder(<#list type.propertyFields as field>${field.name}<#sep>, </#sep></#list><#if filteredParserArguments?has_content><#if type.propertyFields?has_content>, </#if><#list filteredParserArguments as arg>${arg.name}<#sep>, </#sep></#list></#if>);
+        return new ${type.name}Builder(
+        <#list type.propertyFields as field>
+            ${field.name}<#sep>, </#sep>
+        </#list>
+        <#if filteredParserArguments?has_content>
+            <#if type.propertyFields?has_content>, </#if>
+            <#list filteredParserArguments as arg>${arg.name}<#sep>, </#sep>
+            </#list>
+        </#if>
+        <#if (type.propertyFields?has_content || filteredParentParserArguments?has_content) && reservedFields?has_content>,</#if>
+        <#list reservedFields as reservedField>
+            reservedField${reservedField?index}<#sep>, </#sep>
+        </#list>
+        );
     <#elseif type.isDiscriminatedParentTypeDefinition()>
-        return builder.build(<#list type.propertyFields as field>${field.name}<#sep>, </#sep></#list><#if filteredParserArguments?has_content><#if type.propertyFields?has_content>, </#if><#list filteredParserArguments as arg>${arg.name}<#sep>, </#sep></#list></#if>);
+        ${type.name} ${type.name?uncap_first} = builder.build(
+        <#list type.propertyFields as field>
+            ${field.name}<#sep>, </#sep>
+        </#list>
+        <#if filteredParserArguments?has_content>
+            <#if type.propertyFields?has_content>, </#if>
+            <#list filteredParserArguments as arg>
+                ${arg.name}<#sep>, </#sep>
+            </#list>
+        </#if>
+        );
+        <#list reservedFields as reservedField>
+        ${type.name?uncap_first}.reservedField${reservedField?index} = reservedField${reservedField?index};
+        </#list>
+        return ${type.name?uncap_first};
     <#else>
-        return new ${type.name}(<#list type.propertyFields as field>${field.name}<#sep>, </#sep></#list><#if filteredParserArguments?has_content><#if type.propertyFields?has_content>, </#if><#list filteredParserArguments as arg>${arg.name}<#sep>, </#sep></#list></#if>);
+        ${type.name} ${type.name?uncap_first};
+        ${type.name?uncap_first} = new ${type.name}(
+        <#list type.propertyFields as field>
+            ${field.name}<#sep>, </#sep>
+        </#list>
+        <#if filteredParserArguments?has_content>
+            <#if type.propertyFields?has_content>, </#if>
+            <#list filteredParserArguments as arg>
+                ${arg.name}<#sep>, </#sep>
+            </#list>
+        </#if>
+        );
+        <#list reservedFields as reservedField>
+            ${type.name?uncap_first}.reservedField${reservedField?index} = reservedField${reservedField?index};
+        </#list>
+        return ${type.name?uncap_first};
     </#if>
     }
 
     <#if type.isDiscriminatedParentTypeDefinition()>
         public static interface ${type.name}Builder {
-            ${type.name} build(<#list type.propertyFields as field>${helper.getLanguageTypeNameForField(field)} ${field.name}<#sep>, </#sep></#list><#if filteredParserArguments?has_content><#if type.propertyFields?has_content>, </#if><#list filteredParserArguments as arg>${helper.getLanguageTypeNameForTypeReference(arg.type)} ${arg.name}<#sep>, </#sep></#list></#if>);
+            ${type.name} build(
+        <#list type.propertyFields as field>
+            ${helper.getLanguageTypeNameForField(field)} ${field.name}<#sep>, </#sep>
+            </#list>
+        <#if filteredParserArguments?has_content>
+            <#if type.propertyFields?has_content>, </#if>
+            <#list filteredParserArguments as arg>
+                ${helper.getLanguageTypeNameForTypeReference(arg.type)} ${arg.name}<#sep>, </#sep>
+            </#list>
+        </#if>
+        );
         }
 
     </#if>
@@ -797,16 +858,33 @@ public<#if type.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${ty
         public static class ${type.name}Builder implements ${type.parentType.orElseThrow().name}.${type.parentType.orElseThrow().name}Builder {
         <#if type.propertyFields?has_content>
             <#list type.propertyFields as field>
-                private final ${helper.getLanguageTypeNameForField(field)} ${field.name};
+        private final ${helper.getLanguageTypeNameForField(field)} ${field.name};
             </#list>
         </#if>
         <#if filteredParserArguments?has_content>
             <#list filteredParserArguments as arg>
-                private final ${helper.getLanguageTypeNameForTypeReference(arg.type)} ${arg.name};
+        private final ${helper.getLanguageTypeNameForTypeReference(arg.type)} ${arg.name};
             </#list>
         </#if>
+        <#list reservedFields as reservedField>
+        private final ${helper.getLanguageTypeNameForTypeReference(reservedField.type, false)} reservedField${reservedField?index};
+        </#list>
 
-        public ${type.name}Builder(<#list type.propertyFields as field>${helper.getLanguageTypeNameForField(field)} ${field.name}<#sep>, </#sep></#list><#if filteredParserArguments?has_content><#if type.propertyFields?has_content>, </#if><#list filteredParserArguments as arg>${helper.getLanguageTypeNameForTypeReference(arg.type)} ${arg.name}<#sep>, </#sep></#list></#if>) {
+        public ${type.name}Builder(
+        <#list type.propertyFields as field>
+            ${helper.getLanguageTypeNameForField(field)} ${field.name}<#sep>, </#sep>
+        </#list>
+        <#if filteredParserArguments?has_content>
+            <#if type.propertyFields?has_content>, </#if>
+            <#list filteredParserArguments as arg>
+                ${helper.getLanguageTypeNameForTypeReference(arg.type)} ${arg.name}<#sep>, </#sep>
+            </#list>
+        </#if>
+        <#if (type.propertyFields?has_content || filteredParentParserArguments?has_content) && reservedFields?has_content>,</#if>
+        <#list reservedFields as reservedField>
+            ${helper.getLanguageTypeNameForTypeReference(reservedField.type, false)} reservedField${reservedField?index}<#sep>, </#sep>
+        </#list>
+        ) {
         <#list type.propertyFields as field>
             this.${field.name} = ${field.name};
         </#list>
@@ -815,10 +893,36 @@ public<#if type.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${ty
             this.${arg.name} = ${arg.name};
             </#list>
         </#if>
+        <#list reservedFields as reservedField>
+            this.reservedField${reservedField?index} = reservedField${reservedField?index};
+        </#list>
         }
 
-        public ${type.name} build(<#list type.parentType.orElseThrow().asComplexTypeDefinition().orElseThrow().propertyFields as field>${helper.getLanguageTypeNameForField(field)} ${field.name}<#sep>, </#sep></#list><#if filteredParentParserArguments?has_content><#if type.parentType.orElseThrow().asComplexTypeDefinition().orElseThrow().propertyFields?has_content>, </#if><#list filteredParentParserArguments as arg>${helper.getLanguageTypeNameForTypeReference(arg.type)} ${arg.name}<#sep>,  [...]
-            return new ${type.name}(<#list type.allPropertyFields as field>${field.name}<#sep>, </#sep></#list><#if filteredParserArguments?has_content><#if type.allPropertyFields?has_content>, </#if><#list filteredParserArguments as arg>${arg.name}<#sep>, </#sep></#list></#if>);
+        public ${type.name} build(
+        <#list type.parentType.orElseThrow().asComplexTypeDefinition().orElseThrow().propertyFields as field>
+            ${helper.getLanguageTypeNameForField(field)} ${field.name}<#sep>, </#sep>
+        </#list>
+        <#if filteredParentParserArguments?has_content>
+            <#if type.parentType.orElseThrow().asComplexTypeDefinition().orElseThrow().propertyFields?has_content>, </#if>
+                <#list filteredParentParserArguments as arg>
+                ${helper.getLanguageTypeNameForTypeReference(arg.type)} ${arg.name}<#sep>, </#sep>
+                </#list>
+            </#if>
+        ) {
+            ${type.name} ${type.name?uncap_first} = new ${type.name}(
+            <#list type.allPropertyFields as field>
+                ${field.name}<#sep>, </#sep>
+            </#list>
+        <#if filteredParserArguments?has_content>
+            <#if type.allPropertyFields?has_content>, </#if>
+            <#list filteredParserArguments as arg>
+                ${arg.name}<#sep>, </#sep>
+            </#list>
+        </#if>);
+        <#list reservedFields as reservedField>
+            ${type.name?uncap_first}.reservedField${reservedField?index} = reservedField${reservedField?index};
+        </#list>
+            return ${type.name?uncap_first};
         }
     }
 
diff --git a/code-generation/protocol-test/src/main/resources/protocols/test/test.mspec b/code-generation/protocol-test/src/main/resources/protocols/test/test.mspec
index ad2c16aae..7e3ecdc45 100644
--- a/code-generation/protocol-test/src/main/resources/protocols/test/test.mspec
+++ b/code-generation/protocol-test/src/main/resources/protocols/test/test.mspec
@@ -202,6 +202,16 @@
     [reserved       uint 8  '0x00']
 ]
 
+[type ReservedTypeTestParent
+    [reserved       uint 8  '0x00']
+    [simple  uint 8 simpleField]
+    [typeSwitch simpleField
+        ['0' ReservedTypeTestChild
+            [reserved       uint 8  '0x00']
+        ]
+    ]
+]
+
 // TODO: So far only trouble in GO, C seems OK.
 [type VirtualFieldTest
     [simple  uint 8 simpleField]
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldReaderReserved.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldReaderReserved.java
index c3c654528..2c0e3e439 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldReaderReserved.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldReaderReserved.java
@@ -36,8 +36,9 @@ public class FieldReaderReserved<T> implements FieldCommons {
         T reserved = dataReader.read(logicalName, readerArgs);
         if (!Objects.equals(reserved, referenceValue)) {
             LOGGER.info("Expected constant value {} but got {} for reserved field.", referenceValue, reserved);
+            return reserved;
         }
-        return reserved;
+        return null;
     }
 
 }