This is an automated email from the ASF dual-hosted git repository.
hutcheb pushed a commit to branch feature/native_opua_client
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/feature/native_opua_client by
this push:
new 37e612d Implemented a node rearrange for opc:fields based on bit order
37e612d is described below
commit 37e612d9a0d0886fd6cade1ec27cfbab0f446579
Author: hutcheb <[email protected]>
AuthorDate: Mon Apr 19 06:56:26 2021 -0400
Implemented a node rearrange for opc:fields based on bit order
---
build-utils/language-base-freemarker/pom.xml | 6 +
.../BaseFreemarkerLanguageTemplateHelper.java | 7 +
.../templates/java/pojo-template.java.ftlh | 1 -
.../definitions/DefaultComplexTypeDefinition.java | 5 +
.../java/opcua/protocol/OpcuaProtocolLogic.java | 2 +-
protocols/opcua/pom.xml | 10 +-
.../apache/plc4x/protocol/opcua/OpcuaProtocol.java | 4 +
protocols/opcua/src/main/xslt/opc-types.xsl | 160 ++++++++++++++++++++-
8 files changed, 186 insertions(+), 9 deletions(-)
diff --git a/build-utils/language-base-freemarker/pom.xml
b/build-utils/language-base-freemarker/pom.xml
index 8a7602e..727084c 100644
--- a/build-utils/language-base-freemarker/pom.xml
+++ b/build-utils/language-base-freemarker/pom.xml
@@ -61,6 +61,12 @@
<version>0.9.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
+ <dependency>
+ <groupId>net.sf.saxon</groupId>
+ <artifactId>Saxon-HE</artifactId>
+ <version>10.5</version>
+ </dependency>
+
</dependencies>
</project>
diff --git
a/build-utils/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/BaseFreemarkerLanguageTemplateHelper.java
b/build-utils/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/BaseFreemarkerLanguageTemplateHelper.java
index 19fceaa..7e0ef70 100644
---
a/build-utils/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/BaseFreemarkerLanguageTemplateHelper.java
+++
b/build-utils/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/BaseFreemarkerLanguageTemplateHelper.java
@@ -29,6 +29,7 @@ import
org.apache.plc4x.plugins.codegenerator.types.references.SimpleTypeReferen
import
org.apache.plc4x.plugins.codegenerator.types.references.StringTypeReference;
import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
import org.apache.plc4x.plugins.codegenerator.types.terms.*;
+import org.w3c.dom.Node;
import java.util.*;
import java.util.stream.Collectors;
@@ -988,4 +989,10 @@ public abstract class BaseFreemarkerLanguageTemplateHelper
implements Freemarker
return null;
}
+ public static String parseStructuredFields(Object nodeList) {
+ System.out.println((Node) nodeList);
+ System.out.println(nodeList.getClass().getName());
+ return "//Hello";
+ }
+
}
diff --git
a/build-utils/language-java/src/main/resources/templates/java/pojo-template.java.ftlh
b/build-utils/language-java/src/main/resources/templates/java/pojo-template.java.ftlh
index 11d5fb5..f61ff7e 100644
---
a/build-utils/language-java/src/main/resources/templates/java/pojo-template.java.ftlh
+++
b/build-utils/language-java/src/main/resources/templates/java/pojo-template.java.ftlh
@@ -161,7 +161,6 @@ public<#if helper.isDiscriminatedParentTypeDefinition()>
abstract</#if> class ${
}
</#list>
-
<#list type.virtualFields as field>
<#if !helper.isDiscriminatorField(field.name)>
public ${helper.getLanguageTypeNameForField(field)}<#if
field.loopType??>[]</#if> get${field.name?cap_first}() {
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 ac2dc4f..0fd24a5 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
@@ -72,6 +72,11 @@ public class DefaultComplexTypeDefinition extends
DefaultTypeDefinition implemen
field -> (AbstractField) field).collect(Collectors.toList());
}
+ public List<ImplicitField> getImplicitFields() {
+ return fields.stream().filter(field -> field instanceof
ImplicitField).map(
+ field -> (ImplicitField) field).collect(Collectors.toList());
+ }
+
@Override
public List<VirtualField> getVirtualFields() {
return fields.stream().filter(field -> (field instanceof
VirtualField)).map(field -> (VirtualField) field)
diff --git
a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java
b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java
index 459b098..4c14583 100644
---
a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java
+++
b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java
@@ -186,7 +186,7 @@ public class OpcuaProtocolLogic extends
Plc4xProtocolBase<OpcuaAPU> implements H
int requestHandle = getRequestHandle();
- ExpandedNodeId expandedNodeId = new ExpandedNodeIdFourByte(false,
//Namespace Uri Specified
+ ExpandedNodeId expandedNodeId = new ExpandedNodeId(false,
//Namespace Uri Specified
false, //Server Index Specified
NULL_STRING, //Namespace Uri
1L, //Server Index
diff --git a/protocols/opcua/pom.xml b/protocols/opcua/pom.xml
index 172539a..1cc42a8 100644
--- a/protocols/opcua/pom.xml
+++ b/protocols/opcua/pom.xml
@@ -162,10 +162,16 @@
</transformationSets>
</configuration>
<dependencies>
+ <!-- https://mvnrepository.com/artifact/net.sf.saxon/Saxon-HE -->
<dependency>
<groupId>net.sf.saxon</groupId>
- <artifactId>saxon</artifactId>
- <version>8.7</version>
+ <artifactId>Saxon-HE</artifactId>
+ <version>10.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+
<artifactId>plc4x-build-utils-language-base-freemarker</artifactId>
+ <version>0.9.0-SNAPSHOT</version>
</dependency>
</dependencies>
</plugin>
diff --git
a/protocols/opcua/src/main/java/org/apache/plc4x/protocol/opcua/OpcuaProtocol.java
b/protocols/opcua/src/main/java/org/apache/plc4x/protocol/opcua/OpcuaProtocol.java
index 1985acc..e220182 100644
---
a/protocols/opcua/src/main/java/org/apache/plc4x/protocol/opcua/OpcuaProtocol.java
+++
b/protocols/opcua/src/main/java/org/apache/plc4x/protocol/opcua/OpcuaProtocol.java
@@ -23,6 +23,7 @@ import
org.apache.plc4x.plugins.codegenerator.language.mspec.parser.MessageForma
import org.apache.plc4x.plugins.codegenerator.protocol.Protocol;
import org.apache.plc4x.plugins.codegenerator.types.definitions.TypeDefinition;
import
org.apache.plc4x.plugins.codegenerator.types.exceptions.GenerationException;
+import org.w3c.dom.NodeList;
import java.io.InputStream;
import java.util.LinkedHashMap;
@@ -55,4 +56,7 @@ public class OpcuaProtocol implements Protocol {
return typeDefinitionMap;
}
+
+
+
}
diff --git a/protocols/opcua/src/main/xslt/opc-types.xsl
b/protocols/opcua/src/main/xslt/opc-types.xsl
index 2d96d04..7a382db 100644
--- a/protocols/opcua/src/main/xslt/opc-types.xsl
+++ b/protocols/opcua/src/main/xslt/opc-types.xsl
@@ -19,7 +19,10 @@
-->
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:opc="http://opcfoundation.org/BinarySchema/"
+ xmlns:plc4x="https://plc4x.apache.org/"
+ xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ua="http://opcfoundation.org/UA/"
xmlns:tns="http://opcfoundation.org/UA/"
@@ -37,6 +40,23 @@
<xsl:variable name="originaldoc" select="/"/>
+ <xsl:variable name="dataTypeLength" as="map(xs:string, xs:int)">
+ <xsl:map>
+ <xsl:for-each select="//opc:EnumeratedType">
+ <xsl:choose>
+ <xsl:when test="@Name != '' or @LengthInBits != ''">
+ <xsl:map-entry key="concat('ua:', xs:string(@Name))"
select="xs:int(@LengthInBits)"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:map>
+ </xsl:variable>
+
+ <xsl:variable name="bitBuffer" as="map(xs:string, xs:int)">
+ <xsl:map>
+ </xsl:map>
+ </xsl:variable>
+
<xsl:param name="file" select="document($services)"/>
<xsl:param name="statusCodeFile" select="unparsed-text($statusCodes)"/>
<xsl:param name="servicesEnumFile" select="unparsed-text($servicesEnum)"/>
@@ -105,6 +125,7 @@
]
]
+
[type 'RequestHeader'
<xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='RequestHeader']"/>
]
@@ -419,6 +440,10 @@
[optional uint 32 'serverIndex' 'serverIndexSpecified']
]
+[type 'ExpandedNodeId'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='ExpandedNodeId']"/>
+]
+
[discriminatedType 'ExtensionObject'
//A serialized object prefixed with its data type identifier.
[simple ExpandedNodeId 'nodeId']
@@ -434,8 +459,9 @@
]
[type 'PascalString'
- [simple int 32 'stringLength']
- [optional string 'stringLength == -1 ? 0 : stringLength * 8' 'UTF-8'
'stringValue' 'stringLength >= 0']
+ [implicit int 32 'sLength' 'stringValue.length == 0 ? -1 :
stringValue.length']
+ [virtual int 32 'stringLength' 'stringValue.length == -1 ? 0 :
stringValue.length']
+ [simple string 'stringLength * 8' 'UTF-8' 'stringValue']
]
[type 'PascalByteString'
@@ -547,6 +573,7 @@
</xsl:template>
<xsl:template match="opc:EnumeratedType">
+ <xsl:message>[INFO] Parsing Enumerated Datatype - <xsl:value-of
select="@Name"/></xsl:message>
<xsl:apply-templates select="opc:Documentation"/>
<xsl:apply-templates select="opc:EnumeratedValue"/>
</xsl:template>
@@ -556,6 +583,7 @@
</xsl:template>
<xsl:template match="opc:EnumeratedValue">
+ <xsl:message>[INFO] Parsing Enumerated Value - <xsl:value-of
select="@Name"/></xsl:message>
<xsl:variable name="objectTypeId">
<xsl:call-template name="clean-id-string">
<xsl:with-param name="text" select="@Name"/>
@@ -566,6 +594,7 @@
</xsl:template>
<xsl:template match="opc:OpaqueType[not(@Name = 'Duration')]">
+ <xsl:message>[INFO] Parsing Opaque Datatype - <xsl:value-of
select="@Name"/></xsl:message>
<xsl:variable name="objectTypeId">
<xsl:call-template name="clean-id-string">
<xsl:with-param name="text" select="@Name"/>
@@ -578,6 +607,7 @@
</xsl:template>
<xsl:template match="opc:StructuredType[not(@Name = 'Vector')]">
+ <xsl:message>[INFO] Parsing Structured Datatype - <xsl:value-of
select="@Name"/></xsl:message>
<xsl:variable name="objectTypeId">
<xsl:call-template name="clean-id-string">
<xsl:with-param name="text" select="@Name"/>
@@ -586,10 +616,20 @@
</xsl:call-template>
</xsl:variable>
<xsl:apply-templates select="opc:Documentation"/>
- <xsl:apply-templates select="opc:Field"/>
+ <xsl:choose>
+ <xsl:when test="@Name = 'ExpandedNodeId'">
+ <xsl:call-template name="plc4x:parseFields">
+ <xsl:with-param name="baseNode" select="."/>
+ <xsl:with-param
name="currentNodePosition">1</xsl:with-param>
+ <xsl:with-param
name="currentBytePosition">0</xsl:with-param>
+ <xsl:with-param
name="currentBitPosition">0</xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
</xsl:template>
<xsl:template match="opc:Field">
+ <xsl:message>[INFO] Parsing Field - <xsl:value-of
select="@Name"/></xsl:message>
<xsl:variable name="objectTypeId">
<xsl:value-of select="@Name"/>
</xsl:variable>
@@ -615,10 +655,12 @@
<xsl:choose>
<xsl:when test="@LengthField">[array <xsl:value-of
select="$dataType"/> '<xsl:value-of select="$lowerCaseName"/>' count
'<xsl:value-of select="$lowerCaseLengthField"/>']
- </xsl:when>
+ </xsl:when>
<xsl:otherwise>[<xsl:value-of select="$mspecType"/><xsl:text>
</xsl:text><xsl:value-of select="$dataType"/> '<xsl:value-of
select="$lowerCaseName"/>']
- </xsl:otherwise>
+ </xsl:otherwise>
</xsl:choose>
+
+
</xsl:template>
<xsl:template name="clean-id-string">
@@ -692,4 +734,112 @@
]
</xsl:template>
+ <!-- Gets the length in bits of a data type -->
+ <xsl:function name="plc4x:getDataTypeLength" as="xs:integer">
+ <xsl:param name="lengthMap" as="map(xs:string, xs:int)"/>
+ <xsl:param name="datatype"/>
+ <xsl:message>[DEBUG] Getting length of Data Type</xsl:message>
+ <xsl:message>[DEBUG] Data type <xsl:value-of
select="xs:string($datatype/[@TypeName])"/></xsl:message>
+ <xsl:choose>
+ <xsl:when test="map:contains($lengthMap,
xs:string($datatype/[@TypeName]))">
+ <xsl:message>[DEBUG] Bit Length <xsl:value-of
select="$lengthMap(xs:string($datatype/[@TypeName]))"/></xsl:message>
+ <xsl:value-of select="map:get($lengthMap,
xs:string($datatype/[@TypeName]))"/>
+ </xsl:when>
+ <xsl:when test="$datatype/[@TypeName] = 'opc:Bit'">
+ <xsl:choose>
+ <xsl:when test="$datatype/[@Length] != ''">
+ <xsl:value-of select="xs:int($datatype/[@Length])"/>
+ </xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>8</xsl:otherwise>
+ </xsl:choose>
+ </xsl:function>
+
+ <!-- Parse the fields for each type, rearranging all of the bit based
fields -->
+ <xsl:template name="plc4x:parseFields">
+ <xsl:param name="baseNode"/>
+ <xsl:param name="currentNodePosition" as="xs:int"/>
+ <xsl:param name="currentBitPosition" as="xs:int"/>
+ <xsl:param name="currentBytePosition" as="xs:int"/>
+ <xsl:message>Current node Position - <xsl:value-of
select="$currentNodePosition"/>, Bit Position - <xsl:value-of
select="$currentBitPosition"/>, Byte Position - <xsl:value-of
select="$currentBytePosition"/></xsl:message>
+
+ <xsl:for-each select="$baseNode/opc:Field">
+ <xsl:message><xsl:value-of select="position()"/> - <xsl:value-of
select="@TypeName"/></xsl:message>
+ </xsl:for-each>
+ <xsl:choose>
+ <xsl:when test="$currentNodePosition = count($baseNode/opc:Field)">
+ <xsl:apply-templates select="$baseNode/opc:Field"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each
select="($baseNode/opc:Field)[$currentNodePosition]">
+ <xsl:message><xsl:value-of select="position()"/> -
<xsl:value-of select="@TypeName"/></xsl:message>
+ </xsl:for-each>
+ <xsl:choose>
+ <xsl:when test="plc4x:getDataTypeLength($dataTypeLength,
$baseNode/opc:Field[$currentNodePosition][@TypeName]) lt 8">
+ <xsl:choose>
+ <xsl:when test="$currentBitPosition=0">
+ <!-- Put node into current position -->
+ <xsl:message>[DEBUG] First Bit in
Byte</xsl:message>
+ <xsl:call-template name="plc4x:parseFields">
+ <xsl:with-param name="baseNode">
+ <xsl:copy-of
select="$baseNode/opc:Field[position() lt $currentNodePosition]"/>
+ <xsl:copy-of
select="$baseNode/opc:Field[position()=$currentNodePosition]"/>
+ <xsl:copy-of
select="$baseNode/opc:Field[position() gt $currentNodePosition]"/>
+ </xsl:with-param>
+ <xsl:with-param name="currentNodePosition">
+ <xsl:value-of
select="$currentNodePosition + 1"/>
+ </xsl:with-param>
+ <xsl:with-param name="currentBitPosition">
+ <xsl:value-of
select="plc4x:getDataTypeLength($dataTypeLength, $baseNode/opc:Field[position()
= $currentNodePosition][@TypeName]) + $currentBitPosition"/>
+ </xsl:with-param>
+ <xsl:with-param name="currentBytePosition">
+ <xsl:value-of
select="$currentBytePosition + 1"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- Put node into correct position based on
bit and byte position -->
+ <xsl:message>[DEBUG] Additional Bit in
Byte</xsl:message>
+ <xsl:call-template name="plc4x:parseFields">
+ <xsl:with-param name="baseNode">
+ <xsl:copy-of
select="$baseNode/opc:Field[position() lt ($currentNodePosition -
$currentBytePosition)]"/>
+ <xsl:copy-of
select="$baseNode/opc:Field[position()=$currentNodePosition]"/>
+ <xsl:copy-of
select="$baseNode/opc:Field[(position() gt ($currentNodePosition -
$currentBytePosition - 1)) and (position() lt ($currentNodePosition))]"/>
+ <xsl:copy-of
select="$baseNode/opc:Field[position() gt $currentNodePosition]"/>
+ </xsl:with-param>
+ <xsl:with-param name="currentNodePosition">
+ <xsl:value-of
select="$currentNodePosition + 1"/>
+ </xsl:with-param>
+ <xsl:with-param name="currentBitPosition">
+ <xsl:value-of
select="plc4x:getDataTypeLength($dataTypeLength, $baseNode/opc:Field[position()
= $currentNodePosition][@TypeName]) + $currentBitPosition"/>
+ </xsl:with-param>
+ <xsl:with-param name="currentBytePosition">
+ <xsl:value-of
select="$currentBytePosition + 1"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- Put node into current position -->
+ <xsl:message>[DEBUG] not a bit data type</xsl:message>
+ <xsl:call-template name="plc4x:parseFields">
+ <xsl:with-param name="baseNode">
+ <xsl:copy-of
select="$baseNode/opc:Field[position() lt $currentNodePosition]"/>
+ <xsl:copy-of
select="$baseNode/opc:Field[position()=$currentNodePosition]"/>
+ <xsl:copy-of
select="$baseNode/opc:Field[position() gt $currentNodePosition]"/>
+ </xsl:with-param>
+ <xsl:with-param name="currentNodePosition">
+ <xsl:value-of select="$currentNodePosition +
1"/>
+ </xsl:with-param>
+ <xsl:with-param
name="currentBitPosition">0</xsl:with-param>
+ <xsl:with-param
name="currentBytePosition">0</xsl:with-param>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
</xsl:stylesheet>