Bug 574565 - NPE in ContextService if some attributes are not set
Signed-off-by: Matthias Koller <m.koller@peak-solution.de>
diff --git a/api/base/src/main/java/org/eclipse/mdm/api/base/model/BaseEntityFactory.java b/api/base/src/main/java/org/eclipse/mdm/api/base/model/BaseEntityFactory.java
index 6d78c47..2c64c42 100644
--- a/api/base/src/main/java/org/eclipse/mdm/api/base/model/BaseEntityFactory.java
+++ b/api/base/src/main/java/org/eclipse/mdm/api/base/model/BaseEntityFactory.java
@@ -116,7 +116,7 @@
return channelGroup;
}
-
+
/**
* Creates a new {@link Measurement}.
*
diff --git a/nucleus/businessobjects/src/main/java/org/eclipse/mdm/businessobjects/service/ContextService.java b/nucleus/businessobjects/src/main/java/org/eclipse/mdm/businessobjects/service/ContextService.java
index 91de510..195bf38 100644
--- a/nucleus/businessobjects/src/main/java/org/eclipse/mdm/businessobjects/service/ContextService.java
+++ b/nucleus/businessobjects/src/main/java/org/eclipse/mdm/businessobjects/service/ContextService.java
@@ -50,6 +50,8 @@
import org.eclipse.mdm.businessobjects.utils.Serializer;
import org.eclipse.mdm.businessobjects.utils.ServiceUtils;
import org.eclipse.mdm.connector.boundary.ConnectorService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.common.base.Strings;
@@ -58,6 +60,8 @@
import io.vavr.collection.HashMap;
import io.vavr.collection.List;
import io.vavr.collection.Map;
+import io.vavr.control.Option;
+import io.vavr.control.Option.None;
import io.vavr.control.Option.Some;
import io.vavr.control.Try;
@@ -70,6 +74,8 @@
@Stateless
public class ContextService {
+ private static final Logger LOGGER = LoggerFactory.getLogger(ContextService.class);
+
@Inject
private ConnectorService connectorService;
@@ -380,7 +386,7 @@
private DescribableContexts updateContext(TestStep testStep, Try<Map<String, Object>> contextMap,
ContextType[] contextTypes) {
- Map<ContextType, Object> orderedMap = contextMap.get().get(ContextActivity.CONTEXT_GROUP_ORDERED)
+ Map<ContextType, Object> orderedMap = convertNullValueToNone(contextMap.get().get(ContextActivity.CONTEXT_GROUP_ORDERED))
.map(this::transformMap).getOrElse(HashMap.empty())
.mapKeys(t -> ServiceUtils.getContextTypeSupplier(t).get())
.filterKeys(t -> Arrays.asList(contextTypes).contains(t));
@@ -389,7 +395,7 @@
ec.setTestStep(testStep);
ec.setOrdered(updateContextDescribableContext(testStep, orderedMap, contextTypes));
- Map<ContextType, Object> measuredMap = contextMap.get().get(ContextActivity.CONTEXT_GROUP_MEASURED)
+ Map<ContextType, Object> measuredMap = convertNullValueToNone(contextMap.get().get(ContextActivity.CONTEXT_GROUP_MEASURED))
.map(this::transformMap).getOrElse(HashMap.empty())
.mapKeys(t -> ServiceUtils.getContextTypeSupplier(t).get())
.filterKeys(t -> Arrays.asList(contextTypes).contains(t));
@@ -558,24 +564,52 @@
public MDMContextEntity transformToMDMEntity(Map<String, Object> component) {
return new MDMContextEntity(
- component.get("name").map(Object::toString)
- .getOrElseThrow(() -> new MDMEntityAccessException("Missing attribute 'name' in MDMEntity")),
- component.get("id").map(Object::toString).getOrElse(""),
- component.get("type").map(Object::toString).getOrElse(""),
- component.get("sourceType").map(Object::toString).getOrElse(""),
- component.get("sourceName").map(Object::toString).getOrElse(""),
- transformList(component.get("attributes").getOrElseThrow(
+ getValueOrException(component, "name"),
+ getValue(component, "id"),
+ getValue(component, "type"),
+ getValue(component, "sourceType"),
+ getValue(component, "sourceName"),
+ transformList(convertNullValueToNone(component.get("attributes")).getOrElseThrow(
() -> new MDMEntityAccessException("Missing attribute 'attributes' in MDMEntity")))
.map(this::transformMap)
.map(m -> new MDMContextAttribute(
- m.get("name").map(Object::toString)
- .getOrElseThrow(() -> new MDMEntityAccessException(
- "Missing attribute 'name' in MDMAttribute")),
- m.get("value").map(Object::toString)
- .getOrElseThrow(() -> new MDMEntityAccessException(
- "Missing attribute 'value' in MDMAttribute")),
- m.get("unit").map(Object::toString).getOrElse(""),
- m.get("datatype").map(Object::toString).getOrElse(""), null, null, null, null))
+ getValueOrException(m, "name"),
+ getValueOrException(m, "value"),
+ getValue(m, "unit"),
+ getValue(m, "datatype"), null, null, null, null))
.toJavaList());
}
+
+ /**
+ * Check if the option contains null an converts the option to None. Else returns the given option
+ * @param <T>
+ * @param option
+ * @return None if Some(null) is given else option
+ */
+ private <T> Option<T> convertNullValueToNone(Option<T> option) {
+ if (option.contains(null)) {
+ return Option.none();
+ } else {
+ return option;
+ }
+ }
+
+ private String getValue(Map<String, Object> component, String attributeName) {
+ if (component.get(attributeName).contains(null)) {
+ LOGGER.debug("{} is null.", attributeName);
+ return "";
+ } else {
+ return component.get(attributeName).map(Object::toString).getOrElse("");
+ }
+ }
+
+ private String getValueOrException(Map<String, Object> component, String attributeName) {
+ if (component.get(attributeName).contains(null)) {
+ LOGGER.debug("{} is null.", attributeName);
+ throw new MDMEntityAccessException("Attribute '" + attributeName + "' in " + component + " is null.");
+ } else {
+ return component.get(attributeName).map(Object::toString).getOrElseThrow(() -> new MDMEntityAccessException(
+ "Missing attribute '" + attributeName + "' in " + component));
+ }
+ }
}