You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by jf...@apache.org on 2019/12/17 17:27:55 UTC

[plc4x] 01/01: Introduced Complex Types

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

jfeinauer pushed a commit to branch feature/complex-types
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 271f9679bdaf06103a668648ae421435eb458b5c
Author: Julian Feinauer <j....@pragmaticminds.de>
AuthorDate: Tue Dec 17 18:26:56 2019 +0100

    Introduced Complex Types
---
 .../org/apache/plc4x/java/PlcDriverManager.java    |  10 +-
 .../java/org/apache/plc4x/java/api/Changed.java    |   7 ++
 .../org/apache/plc4x/java/api/PlcConnection.java   |   1 +
 .../PlcIncompatibleDatatypeException.java          |   3 +
 .../apache/plc4x/java/api/value/PlcBoolean.java    |  44 ++++++++
 .../apache/plc4x/java/api/value/PlcInteger.java    |  47 ++++++++
 .../org/apache/plc4x/java/api/value/PlcList.java   |  37 +++++++
 .../plc4x/java/api/value/PlcSimpleValue.java       |  27 +++++
 .../org/apache/plc4x/java/api/value/PlcString.java |  40 +++++++
 .../org/apache/plc4x/java/api/value/PlcStruct.java |  37 +++++++
 .../org/apache/plc4x/java/api/value/PlcValue.java  |  83 +++++++++++++++
 .../plc4x/java/api/value/PlcValueAdapter.java      | 118 +++++++++++++++++++++
 .../org/apache/plc4x/java/api/value/PlcValues.java |  45 ++++++++
 .../apache/plc4x/java/api/types/PlcValueTest.java  |  34 ++++++
 14 files changed, 532 insertions(+), 1 deletion(-)

diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/PlcDriverManager.java b/plc4j/api/src/main/java/org/apache/plc4x/java/PlcDriverManager.java
index fb6b09a..95200ec 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/PlcDriverManager.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/PlcDriverManager.java
@@ -18,6 +18,7 @@ under the License.
 */
 package org.apache.plc4x.java;
 
+import org.apache.plc4x.java.api.Changed;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.authentication.PlcAuthentication;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
@@ -89,7 +90,14 @@ public class PlcDriverManager {
         return connection;
     }
 
-    private PlcDriver getDriver(String url) throws PlcConnectionException {
+    /**
+     * Returns suitble driver for protocol or throws an Exception.
+     * @param url Uri to use
+     * @return Driver instance for the given protocol
+     * @throws PlcConnectionException If no Suitable Driver can be found
+     */
+    @Changed
+    public PlcDriver getDriver(String url) throws PlcConnectionException {
         try {
             URI connectionUri = new URI(url);
             String protocol = connectionUri.getScheme();
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/Changed.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/Changed.java
new file mode 100644
index 0000000..98391b2
--- /dev/null
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/Changed.java
@@ -0,0 +1,7 @@
+package org.apache.plc4x.java.api;
+
+/**
+ * Indicates that this is a recent API Change.
+ */
+public @interface Changed {
+}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcConnection.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcConnection.java
index 3838594..5725529 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcConnection.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcConnection.java
@@ -62,6 +62,7 @@ public interface PlcConnection extends AutoCloseable {
      *
      * @throws PlcRuntimeException If the string cannot be parsed
      */
+    @Deprecated
     default PlcField prepareField(String fieldQuery) throws PlcInvalidFieldException {
         throw new PlcRuntimeException("Parse method is not implemented for this connection / driver");
     }
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/exceptions/PlcIncompatibleDatatypeException.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/exceptions/PlcIncompatibleDatatypeException.java
index cb779df..4aeac24 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/exceptions/PlcIncompatibleDatatypeException.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/exceptions/PlcIncompatibleDatatypeException.java
@@ -25,4 +25,7 @@ public class PlcIncompatibleDatatypeException extends PlcRuntimeException {
         super("Incompatible Datatype " + datatype.getName() + " at index " + index);
     }
 
+    public PlcIncompatibleDatatypeException(String message) {
+        super(message);
+    }
 }
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcBoolean.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcBoolean.java
new file mode 100644
index 0000000..1c0cc0c
--- /dev/null
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcBoolean.java
@@ -0,0 +1,44 @@
+package org.apache.plc4x.java.api.value;
+
+public class PlcBoolean extends PlcSimpleValue<Boolean> {
+
+    public PlcBoolean(Boolean value) {
+        super(value, true);
+    }
+
+    public PlcBoolean(boolean bool) {
+        super(bool, false);
+    }
+
+    @Override public boolean isBoolean() {
+        return true;
+    }
+
+    @Override public boolean getBoolean() {
+        return value;
+    }
+
+    @Override public double getDouble() {
+        return value ? 1.0 : 0.0;
+    }
+
+    @Override public float getFloat() {
+        return value ? 1.0f : 0.0f;
+    }
+
+    @Override public long getLong() {
+        return value ? 1 : 0;
+    }
+
+    @Override public int getInteger() {
+        return value ? 1 : 0;
+    }
+
+    @Override public String getString() {
+        return value ? "true" : "false";
+    }
+
+    @Override public String toString() {
+        return Boolean.toString(value);
+    }
+}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcInteger.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcInteger.java
new file mode 100644
index 0000000..8b7e03c
--- /dev/null
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcInteger.java
@@ -0,0 +1,47 @@
+package org.apache.plc4x.java.api.value;
+
+import org.apache.plc4x.java.api.value.PlcSimpleValue;
+
+public class PlcInteger extends PlcSimpleValue<Integer> {
+
+    public PlcInteger(Integer value) {
+        super(value, true);
+    }
+
+    public PlcInteger(int value) {
+        super(value, false);
+    }
+
+    @Override public boolean isString() {
+        return true;
+    }
+
+    @Override public String getString() {
+        return value.toString();
+    }
+
+    @Override public boolean getBoolean() {
+        // We like C
+        return !(value == 0);
+    }
+
+    @Override public double getDouble() {
+        return (double)value;
+    }
+
+    @Override public float getFloat() {
+        return (float)value;
+    }
+
+    @Override public long getLong() {
+        return value;
+    }
+
+    @Override public int getInteger() {
+        return value;
+    }
+
+    @Override public String toString() {
+        return String.valueOf(value);
+    }
+}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcList.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcList.java
new file mode 100644
index 0000000..e307d61
--- /dev/null
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcList.java
@@ -0,0 +1,37 @@
+package org.apache.plc4x.java.api.value;
+
+import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.api.value.PlcValueAdapter;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class PlcList extends PlcValueAdapter {
+
+    private final List<PlcValue> listItems;
+
+    public PlcList(List<PlcValue> listItems) {
+        this.listItems = Collections.unmodifiableList(listItems);
+    }
+
+    @Override public boolean isList() {
+        return true;
+    }
+
+    @Override public int length() {
+        return listItems.size();
+    }
+
+    @Override public PlcValue getIndex(int i) {
+        return listItems.get(i);
+    }
+
+    @Override public List<? extends PlcValue> getList() {
+        return listItems;
+    }
+
+    @Override public String toString() {
+        return "[" + listItems.stream().map(PlcValue::toString).collect(Collectors.joining(",")) + "]";
+    }
+}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcSimpleValue.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcSimpleValue.java
new file mode 100644
index 0000000..37e4ef7
--- /dev/null
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcSimpleValue.java
@@ -0,0 +1,27 @@
+package org.apache.plc4x.java.api.value;
+
+import org.apache.plc4x.java.api.value.PlcValueAdapter;
+
+public abstract class PlcSimpleValue<T> extends PlcValueAdapter {
+
+    protected final T value;
+    protected final boolean isNullable;
+
+    public PlcSimpleValue(T value, boolean isNullable) {
+        this.value = value;
+        this.isNullable = isNullable;
+    }
+
+    @Override public boolean isSimple() {
+        return true;
+    }
+
+    @Override public boolean isNullable() {
+        return isNullable;
+    }
+
+    @Override public boolean isNull() {
+        return isNullable && value == null;
+    }
+
+}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcString.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcString.java
new file mode 100644
index 0000000..ea12bb4
--- /dev/null
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcString.java
@@ -0,0 +1,40 @@
+package org.apache.plc4x.java.api.value;
+
+public class PlcString extends PlcSimpleValue<String> {
+
+    public PlcString(String value) {
+        super(value, true);
+    }
+
+    @Override public boolean isString() {
+        return true;
+    }
+
+    @Override public String getString() {
+        return value;
+    }
+
+    @Override public boolean getBoolean() {
+        return Boolean.parseBoolean(value);
+    }
+
+    @Override public double getDouble() {
+        return Double.parseDouble(value);
+    }
+
+    @Override public float getFloat() {
+        return Float.parseFloat(value);
+    }
+
+    @Override public long getLong() {
+        return Long.parseLong(value);
+    }
+
+    @Override public int getInteger() {
+        return Integer.parseInt(value);
+    }
+
+    @Override public String toString() {
+        return "\"" + value + "\"";
+    }
+}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcStruct.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcStruct.java
new file mode 100644
index 0000000..72df9b0
--- /dev/null
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcStruct.java
@@ -0,0 +1,37 @@
+package org.apache.plc4x.java.api.value;
+
+import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.api.value.PlcValueAdapter;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class PlcStruct extends PlcValueAdapter {
+
+    private final Map<String, PlcValue> map;
+
+    public PlcStruct(Map<String, PlcValue> map) {
+        this.map = Collections.unmodifiableMap(map);
+    }
+
+    @Override public boolean isStruct() {
+        return true;
+    }
+
+    @Override public boolean hasKey(String key) {
+        return map.containsKey(key);
+    }
+
+    @Override public PlcValue getValue(String key) {
+        return map.get(key);
+    }
+
+    @Override public Map<String, ? extends PlcValue> getStruct() {
+        return map;
+    }
+
+    @Override public String toString() {
+        return "{" + map.entrySet().stream().map(entry -> String.format("\"%s\": %s", entry.getKey(), entry.getValue())).collect(Collectors.joining(",")) + "}";
+    }
+}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValue.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValue.java
new file mode 100644
index 0000000..7b5cedf
--- /dev/null
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValue.java
@@ -0,0 +1,83 @@
+package org.apache.plc4x.java.api.value;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Base Type of all Types.
+ */
+public interface PlcValue {
+
+    // Simple Types
+
+    boolean isSimple();
+
+    boolean isNullable();
+
+    boolean isNull();
+
+    // Generic (\o/ Sebastian)
+
+    boolean is(Class<?> clazz);
+
+    boolean isConvertibleTo(Class<?> clazz);
+
+    <T> T get(Class<T> clazz);
+
+    // Boolean
+
+    boolean isBoolean();
+
+    boolean getBoolean();
+
+    // Integer
+
+    boolean isLong();
+
+    long getLong();
+
+    boolean isInteger();
+
+    int getInteger();
+
+    // Floating Point
+
+    boolean isDouble();
+
+    double getDouble();
+
+    boolean isFloat();
+
+    float getFloat();
+
+    // String
+
+    boolean isString();
+
+    String getString();
+
+    // Raw Access
+
+    byte[] getRaw();
+
+    // List Methods
+
+    boolean isList();
+
+    int length();
+
+    PlcValue getIndex(int i);
+
+    List<? extends PlcValue> getList();
+
+    // Struct Methods
+
+    boolean isStruct();
+
+    boolean hasKey(String key);
+
+    PlcValue getValue(String key);
+
+    Map<String, ? extends PlcValue> getStruct();
+
+}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValueAdapter.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValueAdapter.java
new file mode 100644
index 0000000..d8d9032
--- /dev/null
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValueAdapter.java
@@ -0,0 +1,118 @@
+package org.apache.plc4x.java.api.value;
+
+import org.apache.plc4x.java.api.exceptions.PlcIncompatibleDatatypeException;
+
+import java.util.List;
+import java.util.Map;
+
+public class PlcValueAdapter implements PlcValue {
+
+    @Override public boolean isSimple() {
+        return false;
+    }
+
+    @Override public boolean isNullable() {
+        return false;
+    }
+
+    @Override public boolean isNull() {
+        return false;
+    }
+
+    @Override public boolean is(Class<?> clazz) {
+        return false;
+    }
+
+    @Override public boolean isConvertibleTo(Class<?> clazz) {
+        return false;
+    }
+
+    @Override public <T> T get(Class<T> clazz) {
+        throw new PlcIncompatibleDatatypeException("");
+    }
+
+    @Override public boolean isBoolean() {
+        return false;
+    }
+
+    @Override public boolean getBoolean() {
+        throw new PlcIncompatibleDatatypeException("");
+    }
+
+    @Override public boolean isDouble() {
+        return false;
+    }
+
+    @Override public double getDouble() {
+        throw new PlcIncompatibleDatatypeException("");
+    }
+
+    @Override public boolean isFloat() {
+        return false;
+    }
+
+    @Override public float getFloat() {
+        throw new PlcIncompatibleDatatypeException("");
+    }
+
+    @Override public boolean isLong() {
+        return false;
+    }
+
+    @Override public long getLong() {
+        throw new PlcIncompatibleDatatypeException("");
+    }
+
+    @Override public boolean isInteger() {
+        return false;
+    }
+
+    @Override public int getInteger() {
+        throw new PlcIncompatibleDatatypeException("");
+    }
+
+    @Override public boolean isString() {
+        return false;
+    }
+
+    @Override public String getString() {
+        throw new PlcIncompatibleDatatypeException("");
+    }
+
+    @Override public byte[] getRaw() {
+        throw new PlcIncompatibleDatatypeException("");
+    }
+
+    @Override public boolean isList() {
+        return false;
+    }
+
+    @Override public int length() {
+        throw new PlcIncompatibleDatatypeException("");
+    }
+
+    @Override public PlcValue getIndex(int i) {
+        throw new PlcIncompatibleDatatypeException("");
+    }
+
+    @Override public List<? extends PlcValue> getList() {
+        throw new PlcIncompatibleDatatypeException("");
+    }
+
+    @Override public boolean isStruct() {
+        return false;
+    }
+
+    @Override public boolean hasKey(String key) {
+        return false;
+    }
+
+    @Override public PlcValue getValue(String key) {
+        throw new PlcIncompatibleDatatypeException("");
+    }
+
+    @Override public Map<String, ? extends PlcValue> getStruct() {
+        throw new PlcIncompatibleDatatypeException("");
+    }
+
+}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValues.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValues.java
new file mode 100644
index 0000000..eb884ce
--- /dev/null
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValues.java
@@ -0,0 +1,45 @@
+package org.apache.plc4x.java.api.value;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+public class PlcValues {
+
+    public static PlcValue of(String s) {
+        return new PlcString(s);
+    }
+
+    public static PlcValue of(Integer i) {
+        return new PlcInteger(i);
+    }
+
+    public static PlcValue of(int i) {
+        return new PlcInteger(i);
+    }
+
+    public static PlcValue of(Boolean b) {
+        return new PlcBoolean(b);
+    }
+
+    public static PlcValue of(boolean b) {
+        return new PlcBoolean(b);
+    }
+
+    public static PlcValue of(List<PlcValue> list) {
+        return new PlcList(list);
+    }
+
+    public static PlcValue of(PlcValue... items) {
+        return new PlcList(Arrays.asList(items));
+    }
+
+    public static PlcValue of(String key, PlcValue value) {
+        return new PlcStruct(Collections.singletonMap(key, value));
+    }
+
+    public static PlcValue of(Map<String, PlcValue> map) {
+        return new PlcStruct(map);
+    }
+}
diff --git a/plc4j/api/src/test/java/org/apache/plc4x/java/api/types/PlcValueTest.java b/plc4j/api/src/test/java/org/apache/plc4x/java/api/types/PlcValueTest.java
new file mode 100644
index 0000000..334b1f0
--- /dev/null
+++ b/plc4j/api/src/test/java/org/apache/plc4x/java/api/types/PlcValueTest.java
@@ -0,0 +1,34 @@
+package org.apache.plc4x.java.api.types;
+
+import org.apache.plc4x.java.api.exceptions.PlcIncompatibleDatatypeException;
+import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.api.value.PlcValues;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class PlcValueTest {
+
+    @Nested
+    class Complex {
+
+        @Test
+        void complexTestCase_isComplex() {
+            PlcValue value = PlcValues.of("Entry 1", PlcValues.of(
+                PlcValues.of(true),
+                PlcValues.of("Pimmel"),
+                PlcValues.of(false),
+                PlcValues.of("Arsch"),
+                PlcValues.of(1278391)
+            ));
+
+            System.out.println(value);
+
+            assertThrows(PlcIncompatibleDatatypeException.class, value::getBoolean);
+            assertTrue(value.getValue("Entry 1").getIndex(0).getBoolean());
+        }
+    }
+
+}
\ No newline at end of file