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