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 c533745  plc4j: simple xml based writer
c533745 is described below

commit c53374587d2fcb31b1f98bc291192209c41afe8d
Author: Sebastian Rühl <[email protected]>
AuthorDate: Tue Apr 20 14:16:40 2021 +0200

    plc4j: simple xml based writer
---
 plc4go/internal/plc4go/spi/utils/ReadBuffer.go     |   4 +
 .../plc4go/spi/utils/ReadBufferXmlBased.go         |   1 +
 plc4go/internal/plc4go/spi/utils/WriteBuffer.go    |   2 +
 plc4j/drivers/s7/src/test/java/s7IoTest.java       | 121 +++++++++++
 .../plc4x/java/spi/generation/WriteBuffer.java     |   1 +
 .../java/spi/generation/WriteBufferXmlBased.java   | 240 +++++++++++++++++++++
 6 files changed, 369 insertions(+)

diff --git a/plc4go/internal/plc4go/spi/utils/ReadBuffer.go 
b/plc4go/internal/plc4go/spi/utils/ReadBuffer.go
index 0ebb3a3..3404f44 100644
--- a/plc4go/internal/plc4go/spi/utils/ReadBuffer.go
+++ b/plc4go/internal/plc4go/spi/utils/ReadBuffer.go
@@ -24,8 +24,11 @@ import (
 )
 
 type ReadBuffer interface {
+       // GetPos return the current byte position
        GetPos() uint16
+       // HasMore returns true if there are bitLength bits available
        HasMore(bitLength uint8) bool
+       // PullContext signals that we expect now a context with the supplied 
logical name
        PullContext(logicalName string, readerArgs ...WithReaderArgs) error
        ReadBit(logicalName string, readerArgs ...WithReaderArgs) (bool, error)
        ReadUint8(logicalName string, bitLength uint8, readerArgs 
...WithReaderArgs) (uint8, error)
@@ -41,6 +44,7 @@ type ReadBuffer interface {
        ReadFloat64(logicalName string, singed bool, exponentBitLength uint8, 
mantissaBitLength uint8, readerArgs ...WithReaderArgs) (float64, error)
        ReadBigFloat(logicalName string, signed bool, exponentBitLength uint8, 
mantissaBitLength uint8, readerArgs ...WithReaderArgs) (*big.Float, error)
        ReadString(logicalName string, bitLength uint32, readerArgs 
...WithReaderArgs) (string, error)
+       // CloseContext signals that we expect the end of the context with the 
supplied logical name
        CloseContext(logicalName string, readerArgs ...WithReaderArgs) error
 }
 
diff --git a/plc4go/internal/plc4go/spi/utils/ReadBufferXmlBased.go 
b/plc4go/internal/plc4go/spi/utils/ReadBufferXmlBased.go
index 2757976..50d43ac 100644
--- a/plc4go/internal/plc4go/spi/utils/ReadBufferXmlBased.go
+++ b/plc4go/internal/plc4go/spi/utils/ReadBufferXmlBased.go
@@ -56,6 +56,7 @@ func (x *xmlReadBuffer) GetPos() uint16 {
 }
 
 func (x *xmlReadBuffer) HasMore(bitLength uint8) bool {
+       // TODO: work with x.InputOffset() and check if we are at EOF
        return true
 }
 
diff --git a/plc4go/internal/plc4go/spi/utils/WriteBuffer.go 
b/plc4go/internal/plc4go/spi/utils/WriteBuffer.go
index 5bbd1c8..1ea6fcd 100644
--- a/plc4go/internal/plc4go/spi/utils/WriteBuffer.go
+++ b/plc4go/internal/plc4go/spi/utils/WriteBuffer.go
@@ -24,6 +24,7 @@ import (
 )
 
 type WriteBuffer interface {
+       // PushContext signals opening context with the supplied logical name
        PushContext(logicalName string, writerArgs ...WithWriterArgs) error
        WriteBit(logicalName string, value bool, writerArgs ...WithWriterArgs) 
error
        WriteUint8(logicalName string, bitLength uint8, value uint8, writerArgs 
...WithWriterArgs) error
@@ -39,6 +40,7 @@ type WriteBuffer interface {
        WriteFloat64(logicalName string, bitLength uint8, value float64, 
writerArgs ...WithWriterArgs) error
        WriteBigFloat(logicalName string, bitLength uint8, value *big.Float, 
writerArgs ...WithWriterArgs) error
        WriteString(logicalName string, bitLength uint8, encoding string, value 
string, writerArgs ...WithWriterArgs) error
+       // PopContext signals work done with the context with the supplied 
logical name
        PopContext(logicalName string, writerArgs ...WithWriterArgs) error
 }
 
diff --git a/plc4j/drivers/s7/src/test/java/s7IoTest.java 
b/plc4j/drivers/s7/src/test/java/s7IoTest.java
new file mode 100644
index 0000000..977cb9b
--- /dev/null
+++ b/plc4j/drivers/s7/src/test/java/s7IoTest.java
@@ -0,0 +1,121 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+ 
+   http://www.apache.org/licenses/LICENSE-2.0
+ 
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+import org.apache.plc4x.java.s7.readwrite.*;
+import org.apache.plc4x.java.s7.readwrite.io.TPKTPacketIO;
+import org.apache.plc4x.java.s7.readwrite.types.COTPTpduSize;
+import org.apache.plc4x.java.s7.readwrite.types.DataTransportErrorCode;
+import org.apache.plc4x.java.s7.readwrite.types.DataTransportSize;
+import org.apache.plc4x.java.spi.generation.WriteBufferXmlBased;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class s7IoTest {
+
+    @Disabled("Till the output is aligned to the one of golang")
+    @Test
+    void TestS7MessageBytes() throws Exception {
+        String wantXml =
+            "<TPKTPacket>\n" +
+            "    <protocolId bitLength=\"8\" 
dataType=\"uint8\">3</protocolId>\n" +
+            "    <reserved bitLength=\"8\" dataType=\"uint8\">0</reserved>\n" +
+            "    <len bitLength=\"16\" dataType=\"uint16\">29</len>\n" +
+            "    <COTPPacket>\n" +
+            "        <headerLength bitLength=\"8\" 
dataType=\"uint18\">5</headerLength>\n" +
+            "        <tpduCode bitLength=\"8\" 
dataType=\"uint8\">240</tpduCode>\n" +
+            "        <COTPPacketData>\n" +
+            "            <eot bitLength=\"1\" dataType=\"bit\">false</eot>\n" +
+            "            <tpduRef bitLength=\"7\" 
dataType=\"uint8\">13</tpduRef>\n" +
+            "        </COTPPacketData>\n" +
+            "        <parameters>\n" +
+            "            <COTPParameter>\n" +
+            "                <parameterType bitLength=\"8\" 
dataType=\"uint8\">192</parameterType>\n" +
+            "                <parameterLength bitLength=\"8\" 
dataType=\"uint8\">1</parameterLength>\n" +
+            "                <COTPParameterTpduSize>\n" +
+            "                    <COTPTpduSize bitLength=\"8\" 
dataType=\"uint8\" stringRepresentation=\"SIZE_4096\">12</COTPTpduSize>\n" +
+            "                </COTPParameterTpduSize>\n" +
+            "            </COTPParameter>\n" +
+            "        </parameters>\n" +
+            "        <S7Message>\n" +
+            "            <protocolId bitLength=\"8\" 
dataType=\"uint8\">50</protocolId>\n" +
+            "            <messageType bitLength=\"8\" 
dataType=\"uint8\">3</messageType>\n" +
+            "            <reserved bitLength=\"16\" 
dataType=\"uint16\">0</reserved>\n" +
+            "            <tpduReference bitLength=\"16\" 
dataType=\"uint16\">11</tpduReference>\n" +
+            "            <parameterLength bitLength=\"16\" 
dataType=\"uint16\">2</parameterLength>\n" +
+            "            <payloadLength bitLength=\"16\" 
dataType=\"uint16\">5</payloadLength>\n" +
+            "            <S7MessageResponseData>\n" +
+            "                <errorClass bitLength=\"8\" 
dataType=\"uint8\">0</errorClass>\n" +
+            "                <errorCode bitLength=\"8\" 
dataType=\"uint8\">0</errorCode>\n" +
+            "            </S7MessageResponseData>\n" +
+            "            <S7Parameter>\n" +
+            "                <parameterType bitLength=\"8\" 
dataType=\"uint8\">4</parameterType>\n" +
+            "                <S7ParameterReadVarResponse>\n" +
+            "                    <numItems bitLength=\"8\" 
dataType=\"uint8\">1</numItems>\n" +
+            "                </S7ParameterReadVarResponse>\n" +
+            "            </S7Parameter>\n" +
+            "            <S7Payload>\n" +
+            "                <S7PayloadReadVarResponse>\n" +
+            "                    <items>\n" +
+            "                        <S7VarPayloadDataItem>\n" +
+            "                            <DataTransportErrorCode 
bitLength=\"8\" dataType=\"uint8\" 
stringRepresentation=\"OK\">255</DataTransportErrorCode>\n" +
+            "                            <DataTransportSize bitLength=\"8\" 
dataType=\"uint8\" stringRepresentation=\"BIT\">3</DataTransportSize>\n" +
+            "                            <dataLength bitLength=\"16\" 
dataType=\"uint16\">1</dataLength>\n" +
+            "                            <data>\n" +
+            "                                <value bitLength=\"8\" 
dataType=\"int8\">1</value>\n" +
+            "                            </data>\n" +
+            "                            <padding></padding>\n" +
+            "                        </S7VarPayloadDataItem>\n" +
+            "                    </items>\n" +
+            "                </S7PayloadReadVarResponse>\n" +
+            "            </S7Payload>\n" +
+            "        </S7Message>\n" +
+            "    </COTPPacket>\n" +
+            "</TPKTPacket>";
+
+
+        TPKTPacket tpktPacket = new TPKTPacket(
+            new COTPPacketData(
+                new COTPParameter[]{new 
COTPParameterTpduSize(COTPTpduSize.SIZE_4096)},
+                new S7MessageResponseData(
+                    11,
+                    new S7ParameterReadVarResponse((short) 1),
+                    new S7PayloadReadVarResponse(
+                        new S7VarPayloadDataItem[]{
+                            new S7VarPayloadDataItem(
+                                DataTransportErrorCode.OK,
+                                DataTransportSize.BIT,
+                                new byte[]{0x1}
+                            )
+                        }
+                    ),
+                    (short) 0,
+                    (short) 0
+                ),
+                false,
+                (short) 13
+            )
+        );
+        WriteBufferXmlBased writeBufferXmlBased = new WriteBufferXmlBased();
+        TPKTPacketIO.staticSerialize(writeBufferXmlBased, tpktPacket);
+        String gotXml = writeBufferXmlBased.getXmlString();
+        assertEquals(wantXml,gotXml);
+    }
+}
diff --git 
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java 
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java
index cc74f17..23cd4b4 100644
--- 
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java
+++ 
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java
@@ -23,6 +23,7 @@ import java.math.BigDecimal;
 import java.math.BigInteger;
 
 public interface WriteBuffer {
+    // TODO: check if this is really needed or if this is just an artifact
     int getPos();
 
     void pushContext(String logicalName);
diff --git 
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferXmlBased.java
 
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferXmlBased.java
new file mode 100644
index 0000000..6d32130
--- /dev/null
+++ 
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferXmlBased.java
@@ -0,0 +1,240 @@
+/*
+ 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.spi.generation;
+
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.ByteArrayOutputStream;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Stack;
+
+public class WriteBufferXmlBased implements WriteBuffer {
+
+    Stack<Element> stack;
+
+    Document document;
+
+    public WriteBufferXmlBased() {
+        DocumentBuilderFactory documentBuilderFactory = 
DocumentBuilderFactory.newInstance();
+        try {
+            this.document = 
documentBuilderFactory.newDocumentBuilder().newDocument();
+        } catch (ParserConfigurationException e) {
+            throw new PlcRuntimeException(e);
+        }
+        this.stack = new Stack<>();
+    }
+
+    @Override
+    public int getPos() {
+        return 0;
+    }
+
+    @Override
+    public void pushContext(String logicalName) {
+        stack.push(document.createElement(logicalName));
+    }
+
+    @Override
+    public void writeBit(String logicalName, boolean value) throws 
ParseException {
+        Element element = 
document.createElement(sanitizeLogicalName(logicalName));
+        element.setAttribute("dataType", "bit");
+        element.setAttribute("bitLength", "1");
+        
element.appendChild(document.createTextNode(Boolean.valueOf(value).toString()));
+        stack.peek().appendChild(element);
+    }
+
+    @Override
+    public void writeUnsignedByte(String logicalName, int bitLength, byte 
value) throws ParseException {
+        Element element = 
document.createElement(sanitizeLogicalName(logicalName));
+        element.setAttribute("dataType", "uint8");
+        element.setAttribute("bitLength", String.valueOf(bitLength));
+        
element.appendChild(document.createTextNode(Byte.valueOf(value).toString()));
+        stack.peek().appendChild(element);
+    }
+
+    @Override
+    public void writeUnsignedShort(String logicalName, int bitLength, short 
value) throws ParseException {
+        Element element = 
document.createElement(sanitizeLogicalName(logicalName));
+        element.setAttribute("dataType", "uint16");
+        element.setAttribute("bitLength", String.valueOf(bitLength));
+        
element.appendChild(document.createTextNode(Short.valueOf(value).toString()));
+        stack.peek().appendChild(element);
+    }
+
+    @Override
+    public void writeUnsignedInt(String logicalName, int bitLength, int value) 
throws ParseException {
+        Element element = 
document.createElement(sanitizeLogicalName(logicalName));
+        element.setAttribute("dataType", "uint32");
+        element.setAttribute("bitLength", String.valueOf(bitLength));
+        
element.appendChild(document.createTextNode(Integer.valueOf(value).toString()));
+        stack.peek().appendChild(element);
+    }
+
+    @Override
+    public void writeUnsignedLong(String logicalName, int bitLength, long 
value) throws ParseException {
+        Element element = 
document.createElement(sanitizeLogicalName(logicalName));
+        element.setAttribute("dataType", "uint64");
+        element.setAttribute("bitLength", String.valueOf(bitLength));
+        
element.appendChild(document.createTextNode(Long.valueOf(value).toString()));
+        stack.peek().appendChild(element);
+    }
+
+    @Override
+    public void writeUnsignedBigInteger(String logicalName, int bitLength, 
BigInteger value) throws ParseException {
+        Element element = 
document.createElement(sanitizeLogicalName(logicalName));
+        element.setAttribute("dataType", "bigInt");
+        element.setAttribute("bitLength", String.valueOf(bitLength));
+        element.appendChild(document.createTextNode(value.toString()));
+        stack.peek().appendChild(element);
+    }
+
+    @Override
+    public void writeByte(String logicalName, int bitLength, byte value) 
throws ParseException {
+        Element element = 
document.createElement(sanitizeLogicalName(logicalName));
+        element.setAttribute("dataType", "int8");
+        element.setAttribute("bitLength", String.valueOf(bitLength));
+        
element.appendChild(document.createTextNode(Byte.valueOf(value).toString()));
+        stack.peek().appendChild(element);
+    }
+
+    @Override
+    public void writeShort(String logicalName, int bitLength, short value) 
throws ParseException {
+        Element element = 
document.createElement(sanitizeLogicalName(logicalName));
+        element.setAttribute("dataType", "int16");
+        element.setAttribute("bitLength", String.valueOf(bitLength));
+        
element.appendChild(document.createTextNode(Short.valueOf(value).toString()));
+        stack.peek().appendChild(element);
+    }
+
+    @Override
+    public void writeInt(String logicalName, int bitLength, int value) throws 
ParseException {
+        Element element = 
document.createElement(sanitizeLogicalName(logicalName));
+        element.setAttribute("dataType", "int32");
+        element.setAttribute("bitLength", String.valueOf(bitLength));
+        
element.appendChild(document.createTextNode(Integer.valueOf(value).toString()));
+        stack.peek().appendChild(element);
+    }
+
+    @Override
+    public void writeLong(String logicalName, int bitLength, long value) 
throws ParseException {
+        Element element = 
document.createElement(sanitizeLogicalName(logicalName));
+        element.setAttribute("dataType", "int64");
+        element.setAttribute("bitLength", String.valueOf(bitLength));
+        
element.appendChild(document.createTextNode(Long.valueOf(value).toString()));
+        stack.peek().appendChild(element);
+    }
+
+    @Override
+    public void writeBigInteger(String logicalName, int bitLength, BigInteger 
value) throws ParseException {
+        Element element = 
document.createElement(sanitizeLogicalName(logicalName));
+        element.setAttribute("dataType", "bigInt");
+        element.setAttribute("bitLength", String.valueOf(bitLength));
+        element.appendChild(document.createTextNode(value.toString()));
+        stack.peek().appendChild(element);
+    }
+
+    @Override
+    public void writeFloat(String logicalName, float value, int bitsExponent, 
int bitsMantissa) throws ParseException {
+        Element element = 
document.createElement(sanitizeLogicalName(logicalName));
+        element.setAttribute("dataType", "float32");
+        element.setAttribute("bitLength", String.valueOf((value < 0 ? 1 : 0) + 
bitsExponent + bitsMantissa));
+        
element.appendChild(document.createTextNode(Float.valueOf(value).toString()));
+        stack.peek().appendChild(element);
+    }
+
+    @Override
+    public void writeDouble(String logicalName, double value, int 
bitsExponent, int bitsMantissa) throws ParseException {
+        Element element = 
document.createElement(sanitizeLogicalName(logicalName));
+        element.setAttribute("dataType", "float64");
+        element.setAttribute("bitLength", String.valueOf((value < 0 ? 1 : 0) + 
bitsExponent + bitsMantissa));
+        
element.appendChild(document.createTextNode(Double.valueOf(value).toString()));
+        stack.peek().appendChild(element);
+    }
+
+    @Override
+    public void writeBigDecimal(String logicalName, int bitLength, BigDecimal 
value) throws ParseException {
+        Element element = 
document.createElement(sanitizeLogicalName(logicalName));
+        element.setAttribute("dataType", "bigFloat");
+        element.setAttribute("bitLength", String.valueOf(bitLength));
+        element.appendChild(document.createTextNode(value.toString()));
+        stack.peek().appendChild(element);
+    }
+
+    @Override
+    public void writeString(String logicalName, int bitLength, String 
encoding, String value) throws ParseException {
+        Element element = 
document.createElement(sanitizeLogicalName(logicalName));
+        element.setAttribute("dataType", "string");
+        element.setAttribute("bitLength", String.valueOf(bitLength));
+        element.appendChild(document.createTextNode(value));
+        stack.peek().appendChild(element);
+    }
+
+    @Override
+    public void popContext(String logicalName) {
+        Element currentContext = stack.pop();
+        if (!currentContext.getTagName().equals(logicalName)) {
+            throw new PlcRuntimeException("Unexpected pop context '" + 
currentContext.getTagName() + '\'');
+        }
+        if (stack.isEmpty()) {
+            document.appendChild(currentContext);
+            return;
+        }
+        stack.peek().appendChild(currentContext);
+    }
+
+    public String getXmlString() {
+        try {
+            Transformer transformer = 
TransformerFactory.newInstance().newTransformer();
+            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, 
"yes");
+            //transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, 
"roles.dtd");
+            
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount";, "4");
+
+            ByteArrayOutputStream byteArrayOutputStream = new 
ByteArrayOutputStream();
+            transformer.transform(new DOMSource(document),
+                new StreamResult(byteArrayOutputStream));
+
+            return byteArrayOutputStream.toString();
+        } catch (TransformerException e) {
+            throw new PlcRuntimeException(e);
+        }
+    }
+
+
+    private String sanitizeLogicalName(String logicalName) {
+        if (logicalName.equals("")) {
+            return "value";
+        }
+        return logicalName;
+    }
+}

Reply via email to