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 2018/10/26 20:35:17 UTC

[incubator-plc4x] 01/06: [plc4j-opm] added fqn of entity to fields on request

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

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

commit 1c51cfda5e6e8a2d3aed2140fdfdcf21feacc5b5
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Oct 26 22:02:31 2018 +0200

    [plc4j-opm] added fqn of entity to fields on request
---
 .../apache/plc4x/java/opm/PlcEntityManager.java    | 113 +++++++++++----------
 .../plc4x/java/opm/PlcEntityManagerTest.java       |  44 ++++----
 plc4j/utils/opm/src/test/resources/logback.xml     |  36 +++++++
 3 files changed, 119 insertions(+), 74 deletions(-)

diff --git a/plc4j/utils/opm/src/main/java/org/apache/plc4x/java/opm/PlcEntityManager.java b/plc4j/utils/opm/src/main/java/org/apache/plc4x/java/opm/PlcEntityManager.java
index 59e6300..f42461f 100644
--- a/plc4j/utils/opm/src/main/java/org/apache/plc4x/java/opm/PlcEntityManager.java
+++ b/plc4j/utils/opm/src/main/java/org/apache/plc4x/java/opm/PlcEntityManager.java
@@ -23,6 +23,7 @@ import net.bytebuddy.ByteBuddy;
 import net.bytebuddy.implementation.MethodDelegation;
 import net.bytebuddy.implementation.bind.annotation.*;
 import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
@@ -41,6 +42,7 @@ import java.math.BigInteger;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
+import java.util.Arrays;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
@@ -105,18 +107,14 @@ public class PlcEntityManager {
 
             PlcReadRequest.Builder requestBuilder = connection.readRequestBuilder();
 
-            // Do the necessary queries for all fields
-            // HashMap<ReadRequestItem<?>, Field> requestItems = new HashMap<>();
-            for (Field field : clazz.getDeclaredFields()) {
-                PlcField fieldAnnotation = field.getAnnotation(PlcField.class);
-                if (fieldAnnotation == null) {
-                    // Ignore that field
-                    continue;
-                }
-                // Create the suitable Request
-                String query = fieldAnnotation.value();
-                requestBuilder.addItem(field.getName(), query);
-            }
+            Arrays.stream(clazz.getDeclaredFields())
+                .filter(field -> field.isAnnotationPresent(PlcField.class))
+                .forEach(field ->
+                    requestBuilder.addItem(
+                        field.getDeclaringClass().getName() + "." + field.getName(),
+                        field.getAnnotation(PlcField.class).value()
+                    )
+                );
 
             // Build the request
             PlcReadRequest request;
@@ -142,7 +140,8 @@ public class PlcEntityManager {
 
             // Fill all requested fields
             for (String fieldName : response.getFieldNames()) {
-                setField(clazz, instance, response, fieldName);
+                String targetFieldName = StringUtils.substringAfterLast(fieldName, ".");
+                setField(clazz, instance, response, targetFieldName, fieldName);
             }
             return instance;
         } catch (PlcConnectionException e) {
@@ -249,31 +248,37 @@ public class PlcEntityManager {
      * @throws OPMException
      */
     private void refetchAllFields(Object o) throws OPMException {
+        // Don't log o here as this would cause a second request against a plc so don't touch it, or if you log be aware of that
         Class<?> superclass = o.getClass().getSuperclass();
         PlcEntity plcEntity = superclass.getAnnotation(PlcEntity.class);
+        if (plcEntity == null) {
+            throw new OPMException("Non PlcEntity supplied");
+        }
 
         try (PlcConnection connection = driverManager.getConnection(plcEntity.value())) {
             // Catch the exception, if no reader present (see below)
             // Build the query
-            PlcReadRequest.Builder builder = connection.readRequestBuilder();
-            for (Field field : superclass.getDeclaredFields()) {
-                // Check if the field has an annotation
-                PlcField plcField = field.getDeclaredAnnotation(PlcField.class);
-                if (plcField != null) {
-                    LOGGER.trace("Adding field " + field.getName() + " to request as " + plcField.value());
-                    builder.addItem(field.getName(), plcField.value());
-                }
+            PlcReadRequest.Builder requestBuilder = connection.readRequestBuilder();
 
-            }
-            PlcReadRequest request = builder.build();
+            Arrays.stream(superclass.getDeclaredFields())
+                .filter(field -> field.isAnnotationPresent(PlcField.class))
+                .forEach(field ->
+                    requestBuilder.addItem(
+                        field.getDeclaringClass().getName() + "." + field.getName(),
+                        field.getAnnotation(PlcField.class).value()
+                    )
+                );
+
+            PlcReadRequest request = requestBuilder.build();
 
             PlcReadResponse response = getPlcReadResponse(request);
 
             // Fill all requested fields
             for (String fieldName : response.getFieldNames()) {
                 LOGGER.trace("Value for field " + fieldName + " is " + response.getObject(fieldName));
+                String clazzFieldName = StringUtils.substringAfterLast(fieldName, ".");
                 try {
-                    setField(o.getClass().getSuperclass(), o, response, fieldName);
+                    setField(o.getClass().getSuperclass(), o, response, clazzFieldName, fieldName);
                 } catch (NoSuchFieldException | IllegalAccessException e) {
                     throw new PlcRuntimeException(e);
                 }
@@ -320,63 +325,61 @@ public class PlcEntityManager {
      * This is one by looking for a field in the class and a response item
      * which is equal to the given fieldName parameter.
      *
-     * @param o         Object to set the value on
-     * @param response  Response to fetch the response from
-     * @param fieldName Name of the field in the object and the response
+     * @param o               Object to set the value on
+     * @param response        Response to fetch the response from
+     * @param targetFieldName Name of the field in the object
+     * @param sourceFieldName Name of the field in the response
      * @throws NoSuchFieldException
      * @throws IllegalAccessException
      */
-    private void setField(Class<?> clazz, Object o, PlcReadResponse response, String fieldName) throws NoSuchFieldException, IllegalAccessException {
-        Field field = clazz.getDeclaredField(fieldName);
+    private void setField(Class<?> clazz, Object o, PlcReadResponse response, String targetFieldName, String sourceFieldName) throws NoSuchFieldException, IllegalAccessException {
+        LOGGER.debug("setField on clazz: {}, Object: {}, response: {}, targetFieldName: {}, sourceFieldName:{} ", clazz, o, response, targetFieldName, sourceFieldName);
+        Field field = clazz.getDeclaredField(targetFieldName);
         field.setAccessible(true);
         try {
-            field.set(o, getTyped(field.getType(), response, fieldName));
+            field.set(o, getTyped(field.getType(), response, sourceFieldName));
         } catch (ClassCastException e) {
             // TODO should we simply fail here?
-            LOGGER.warn("Unable to assign return value {} to field {} with type {}", response.getObject(fieldName), fieldName, field.getType(), e);
+            LOGGER.warn("Unable to assign return value {} to field {} with type {}", response.getObject(sourceFieldName), targetFieldName, field.getType(), e);
         }
     }
 
-    private Object getTyped(Class<?> clazz, PlcReadResponse response, String fieldName) {
-        Object responseObject = response.getObject(fieldName);
-        if (responseObject == null) {
-            // TODO: shall we better throw an exception or is object never null?
-            return null;
-        }
+    private Object getTyped(Class<?> clazz, PlcReadResponse response, String sourceFieldName) {
+        LOGGER.debug("getTyped clazz: {}, response: {}, fieldName: {}", clazz, response, sourceFieldName);
         if (clazz.isPrimitive()) {
             if (clazz == boolean.class) {
-                return response.getBoolean(fieldName);
+                return response.getBoolean(sourceFieldName);
             } else if (clazz == byte.class) {
-                return response.getByte(fieldName);
+                return response.getByte(sourceFieldName);
             } else if (clazz == short.class) {
-                return response.getShort(fieldName);
+                return response.getShort(sourceFieldName);
             } else if (clazz == int.class) {
-                return response.getInteger(fieldName);
+                return response.getInteger(sourceFieldName);
             } else if (clazz == long.class) {
-                return response.getLong(fieldName);
+                return response.getLong(sourceFieldName);
             }
         }
 
         if (clazz == Boolean.class) {
-            return response.getBoolean(fieldName);
+            return response.getBoolean(sourceFieldName);
         } else if (clazz == Byte.class) {
-            return response.getByte(fieldName);
+            return response.getByte(sourceFieldName);
         } else if (clazz == Short.class) {
-            return response.getShort(fieldName);
+            return response.getShort(sourceFieldName);
         } else if (clazz == Integer.class) {
-            return response.getInteger(fieldName);
+            return response.getInteger(sourceFieldName);
         } else if (clazz == Long.class) {
-            return response.getLong(fieldName);
+            return response.getLong(sourceFieldName);
         } else if (clazz == BigInteger.class) {
-            return response.getBigInteger(fieldName);
+            return response.getBigInteger(sourceFieldName);
         } else if (clazz == Float.class) {
-            return response.getFloat(fieldName);
+            return response.getFloat(sourceFieldName);
         } else if (clazz == Double.class) {
-            return response.getDouble(fieldName);
+            return response.getDouble(sourceFieldName);
         } else if (clazz == BigDecimal.class) {
-            return response.getBigDecimal(fieldName);
+            return response.getBigDecimal(sourceFieldName);
         } else if (clazz == String.class) {
-            return response.getString(fieldName);
+            return response.getString(sourceFieldName);
         } else if (clazz == LocalTime.class) {
             // TODO: where are the methods for this?
             throw new UnsupportedOperationException("no supported yet for " + clazz);
@@ -387,11 +390,13 @@ public class PlcEntityManager {
             // TODO: where are the methods for this?
             throw new UnsupportedOperationException("no supported yet for " + clazz);
         } else if (clazz == byte[].class) {
-            return ArrayUtils.toPrimitive(response.getByteArray(fieldName));
+            return ArrayUtils.toPrimitive(response.getByteArray(sourceFieldName));
         } else if (clazz == Byte[].class) {
-            return response.getByteArray(fieldName);
+            return response.getByteArray(sourceFieldName);
         }
 
+        // Fallback
+        Object responseObject = response.getObject(sourceFieldName);
         if (clazz.isAssignableFrom(responseObject.getClass())) {
             return responseObject;
         }
diff --git a/plc4j/utils/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerTest.java b/plc4j/utils/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerTest.java
index dea046e..d161e62 100644
--- a/plc4j/utils/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerTest.java
+++ b/plc4j/utils/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerTest.java
@@ -39,6 +39,7 @@ import org.mockito.Mockito;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 import java.util.function.Function;
 import java.util.stream.Collectors;
@@ -68,8 +69,9 @@ public class PlcEntityManagerTest {
     @Test
     public void read() throws OPMException, PlcConnectionException {
         Map<String, BaseDefaultFieldItem> results = new HashMap<>();
-        results.put("counter", new DefaultIntegerFieldItem(1));
-        results.put("counter2", new DefaultIntegerFieldItem(1));
+        String prefix = MyEntity.class.getName() + ".";
+        results.put(prefix + "counter", new DefaultIntegerFieldItem(1));
+        results.put(prefix + "counter2", new DefaultLongFieldItem(1l));
         PlcEntityManager manager = getPlcEntityManager(results);
 
         MyEntity myEntity = manager.read(MyEntity.class);
@@ -81,13 +83,14 @@ public class PlcEntityManagerTest {
     @Test
     public void readComplexObject() throws PlcConnectionException, OPMException {
         Map<String, BaseDefaultFieldItem> map = new HashMap<>();
-        map.put("boolVar", new DefaultBooleanFieldItem(true));
-        map.put("byteVar", new DefaultByteFieldItem((byte) 1));
-        map.put("shortVar", new DefaultShortFieldItem((short) 1));
-        map.put("intVar", new DefaultIntegerFieldItem(1));
-        map.put("longVar", new DefaultLongFieldItem(1l));
-        map.put("boxedLongVar", new DefaultLongFieldItem(1L));
-        map.put("stringVar", new DefaultStringFieldItem("Hallo"));
+        String prefix = ConnectedEntity.class.getName() + ".";
+        map.put(prefix + "boolVar", new DefaultBooleanFieldItem(true));
+        map.put(prefix + "byteVar", new DefaultByteFieldItem((byte) 1));
+        map.put(prefix + "shortVar", new DefaultShortFieldItem((short) 1));
+        map.put(prefix + "intVar", new DefaultIntegerFieldItem(1));
+        map.put(prefix + "longVar", new DefaultLongFieldItem(1l));
+        map.put(prefix + "boxedLongVar", new DefaultLongFieldItem(1L));
+        map.put(prefix + "stringVar", new DefaultStringFieldItem("Hallo"));
         PlcEntityManager manager = getPlcEntityManager(map);
 
         ConnectedEntity connect = manager.read(ConnectedEntity.class);
@@ -101,15 +104,16 @@ public class PlcEntityManagerTest {
     }
 
     @Test
-    public void connec_callComplexMethodt() throws PlcConnectionException, OPMException {
+    public void connect_callComplexMethod() throws PlcConnectionException, OPMException {
         Map<String, BaseDefaultFieldItem> map = new HashMap<>();
-        map.put("boolVar", new DefaultBooleanFieldItem(true));
-        map.put("byteVar", new DefaultByteFieldItem((byte) 1));
-        map.put("shortVar", new DefaultShortFieldItem((short) 1));
-        map.put("intVar", new DefaultIntegerFieldItem(1));
-        map.put("longVar", new DefaultLongFieldItem(1l));
-        map.put("boxedLongVar", new DefaultLongFieldItem(1L));
-        map.put("stringVar", new DefaultStringFieldItem("Hallo"));
+        String prefix = ConnectedEntity.class.getName() + ".";
+        map.put(prefix + "boolVar", new DefaultBooleanFieldItem(true));
+        map.put(prefix + "byteVar", new DefaultByteFieldItem((byte) 1));
+        map.put(prefix + "shortVar", new DefaultShortFieldItem((short) 1));
+        map.put(prefix + "intVar", new DefaultIntegerFieldItem(1));
+        map.put(prefix + "longVar", new DefaultLongFieldItem(1l));
+        map.put(prefix + "boxedLongVar", new DefaultLongFieldItem(1L));
+        map.put(prefix + "stringVar", new DefaultStringFieldItem("Hallo"));
         PlcEntityManager manager = getPlcEntityManager(map);
 
         ConnectedEntity connect = manager.connect(ConnectedEntity.class);
@@ -165,11 +169,11 @@ public class PlcEntityManagerTest {
             Map<String, Pair<PlcResponseCode, BaseDefaultFieldItem>> map = readRequest.getFieldNames().stream()
                 .collect(Collectors.toMap(
                     Function.identity(),
-                    s -> Pair.of(PlcResponseCode.OK, responses.get(s))
+                    s -> Pair.of(PlcResponseCode.OK, Objects.requireNonNull(responses.get(s), s + " not found"))
                 ));
-            return CompletableFuture.completedFuture(new DefaultPlcReadResponse(((InternalPlcReadRequest) readRequest), map));
+            return CompletableFuture.completedFuture(new DefaultPlcReadResponse((InternalPlcReadRequest) readRequest, map));
         };
-        when(connection.readRequestBuilder()).thenReturn(new DefaultPlcReadRequest.Builder(reader, getFieldHandler()));
+        when(connection.readRequestBuilder()).then(invocation -> new DefaultPlcReadRequest.Builder(reader, getFieldHandler()));
 
         return new PlcEntityManager(mock);
     }
diff --git a/plc4j/utils/opm/src/test/resources/logback.xml b/plc4j/utils/opm/src/test/resources/logback.xml
new file mode 100644
index 0000000..8b49981
--- /dev/null
+++ b/plc4j/utils/opm/src/test/resources/logback.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+<configuration xmlns="http://ch.qos.logback/xml/ns/logback"
+               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+               xsi:schemaLocation="http://ch.qos.logback/xml/ns/logback https://raw.githubusercontent.com/enricopulatzo/logback-XSD/master/src/main/xsd/logback.xsd">
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <!-- encoders are assigned the type
+         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
+    <encoder>
+      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+    </encoder>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="STDOUT"/>
+  </root>
+
+</configuration>
\ No newline at end of file