/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.components.converger.execution;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectWriter;
import org.codehaus.jackson.node.ArrayNode;
import org.codehaus.jackson.node.JsonNodeFactory;
import org.codehaus.jackson.node.ObjectNode;
import org.codehaus.jackson.node.TextNode;
import de.rcenvironment.components.converger.common.ConvergerComponentConstants;
import de.rcenvironment.core.component.update.api.PersistentComponentDescription;
import de.rcenvironment.core.component.update.api.PersistentComponentDescriptionUpdaterUtils;
import de.rcenvironment.core.component.update.api.PersistentDescriptionFormatVersion;
import de.rcenvironment.core.component.update.spi.PersistentComponentDescriptionUpdater;
import de.rcenvironment.core.datamodel.api.TypedDatumService;
import de.rcenvironment.core.datamodel.types.api.FloatTD;
import de.rcenvironment.core.utils.common.JsonUtils;
/**
* Implementation of {@link PersistentComponentDescriptionUpdater}.
*
* @author Sascha Zur
* @author Doreen Seider
*/
public class ConvergerPersistentComponentDescriptionUpdater implements PersistentComponentDescriptionUpdater {
private static final String START_SUFFIX = "_start";
private static final String CONVERGED_SUFFIX = "_converged";
private static final String OUTER_LOOP_DONE = "outerLoopDone";
private static final String REQUIRED = "Required";
private static final String INPUT_EXECUTION_CONSTRAINT = "inputExecutionConstraint_4aae3eea";
private static final String VALUE_TO_CONVERGE = "valueToConverge";
private static final String SELF_LOOP_ENDPOINT = "SelfLoopEndpoint";
private static final String LOOP_ENDPOINT_TYPE = "loopEndpointType_5e0ed1cd";
private static final String OUTER_LOOP_ENDPOINT = "OuterLoopEndpoint";
private static final String METADATA = "metadata";
private static final String BOOLEAN = "Boolean";
private static final String IDENTIFIER = "identifier";
private static final String NAME = "name";
private static final String DATATYPE = "datatype";
private static final String DYNAMIC_OUTPUTS = "dynamicOutputs";
private static final String DYNAMIC_INPUTS = "dynamicInputs";
private static final String V1_0 = "1.0";
private static final String CONFIGURATION = "configuration";
private static final String EP_IDENTIFIER = "epIdentifier";
private static final String COLON = ":";
private static final String STATIC_OUTPUTS = "staticOutputs";
private static final String STATIC_INPUTS = "staticInputs";
private static final String V3_0 = "3.0";
private static final String V3_1 = "3.1";
private static final String V3_2 = "3.2";
private static final String V4_0 = "4.0";
private static final String V4_1 = "4.1";
private static final String V5_0 = "5";
private static final String V5_1 = "5.1";
private static final String V5_1_1 = "5.1.1";
private static final String V6 = "6";
private static TypedDatumService typedDatumService;
@Override
public String[] getComponentIdentifiersAffectedByUpdate() {
return ConvergerComponentConstants.COMPONENT_IDS;
}
@Override
public int getFormatVersionsAffectedByUpdate(String persistentComponentDescriptionVersion, boolean silent) {
int versions = PersistentDescriptionFormatVersion.NONE;
// Update 1 : Version < 1.0
if (!silent && (persistentComponentDescriptionVersion == null
|| persistentComponentDescriptionVersion.compareTo(V1_0) < 0)) {
versions = versions | PersistentDescriptionFormatVersion.BEFORE_VERSON_THREE;
}
// Update 2 : 1.0 <= Version < 3.0
if (!silent && persistentComponentDescriptionVersion != null
&& persistentComponentDescriptionVersion.compareTo(V3_0) < 0) {
versions = versions | PersistentDescriptionFormatVersion.FOR_VERSION_THREE;
}
// Update 3 non-silent : 3.0 -> latest
if (!silent && persistentComponentDescriptionVersion != null
&& persistentComponentDescriptionVersion.compareTo(V6) < 0) {
versions = versions | PersistentDescriptionFormatVersion.AFTER_VERSION_THREE;
}
// Update 3 silent : 3.0 -> latest
if (silent && persistentComponentDescriptionVersion != null
&& persistentComponentDescriptionVersion.compareTo(V5_1_1) < 0) {
versions = versions | PersistentDescriptionFormatVersion.AFTER_VERSION_THREE;
}
return versions;
}
@Override
public PersistentComponentDescription performComponentDescriptionUpdate(int formatVersion, PersistentComponentDescription description,
boolean silent) throws IOException {
if (!silent) { // called after "silent" was called
if (formatVersion == PersistentDescriptionFormatVersion.BEFORE_VERSON_THREE) {
description = firstUpdate(description);
description.setComponentVersion(V1_0);
} else if (formatVersion == PersistentDescriptionFormatVersion.FOR_VERSION_THREE) {
description = secondUpdate(description);
description.setComponentVersion(V3_0);
} else if (formatVersion == PersistentDescriptionFormatVersion.AFTER_VERSION_THREE) {
switch (description.getComponentVersion()) {
case V3_0:
description = updateFrom30To31(description);
case V3_1:
description = updateFrom31To32(description);
case V3_2:
description = updateFrom32To40(description);
case V4_0:
description = updateFrom40To41(description);
case V4_1:
description = updateFrom41To5(description);
case V5_0:
description = updateFrom50To51(description);
case V5_1:
description = updateFrom51To511(description);
case V5_1_1:
description = updateFrom511To6(description);
default:
// nothing to do here
}
}
} else { // called first (before non-silent)
if (formatVersion == PersistentDescriptionFormatVersion.AFTER_VERSION_THREE) {
switch (description.getComponentVersion()) {
case V5_0:
description = updateFrom50To51(description);
case V5_1:
description = updateFrom51To511(description);
default:
// nothing to do here
}
}
}
return description;
}
private PersistentComponentDescription updateFrom511To6(PersistentComponentDescription description)
throws JsonProcessingException, IOException {
description =
PersistentComponentDescriptionUpdaterUtils.removeOuterLoopDoneEndpoints(description);
description = PersistentComponentDescriptionUpdaterUtils.removeEndpointCharacterInfoFromMetaData(description);
description = PersistentComponentDescriptionUpdaterUtils.reassignEndpointIdentifiers(description, DYNAMIC_INPUTS, "toForward",
"startToForward", START_SUFFIX);
description = PersistentComponentDescriptionUpdaterUtils.reassignEndpointIdentifiers(description, DYNAMIC_OUTPUTS, "toForward",
"finalToForward", CONVERGED_SUFFIX);
description =
PersistentComponentDescriptionUpdaterUtils.reassignEndpointIdentifiers(description, DYNAMIC_INPUTS, VALUE_TO_CONVERGE,
"startToConverge", START_SUFFIX);
description =
PersistentComponentDescriptionUpdaterUtils.reassignEndpointIdentifiers(description, DYNAMIC_OUTPUTS, VALUE_TO_CONVERGE,
"finalToConverge", CONVERGED_SUFFIX);
description.setComponentVersion(V6);
return description;
}
private PersistentComponentDescription updateFrom51To511(PersistentComponentDescription description)
throws JsonProcessingException, IOException {
description =
PersistentComponentDescriptionUpdaterUtils.updateFaultToleranceOfLoopDriver(description);
description.setComponentVersion(V5_1_1);
return description;
}
private PersistentComponentDescription updateFrom50To51(PersistentComponentDescription description)
throws JsonProcessingException, IOException {
ObjectMapper mapper = JsonUtils.getDefaultObjectMapper();
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
ObjectNode configNode = (ObjectNode) node.get(CONFIGURATION);
configNode.put(ConvergerComponentConstants.NOT_CONVERGED_IGNORE, true);
configNode.put(ConvergerComponentConstants.NOT_CONVERGED_FAIL, false);
configNode.put(ConvergerComponentConstants.NOT_CONVERGED_NOT_A_VALUE, false);
JsonNode dynamicOutputs = node.get(DYNAMIC_OUTPUTS);
if (dynamicOutputs != null) {
List<ObjectNode> newOutputEndpoints = new ArrayList<ObjectNode>();
for (JsonNode outputEndpoint : dynamicOutputs) {
String outputName = outputEndpoint.get(NAME).getTextValue();
String outputEndpointId = outputEndpoint.get(EP_IDENTIFIER).getTextValue();
if (outputEndpointId.equals(VALUE_TO_CONVERGE) && !outputName.endsWith(CONVERGED_SUFFIX)) {
ObjectNode convergedEndpoint = mapper.createObjectNode();
convergedEndpoint.put(NAME, TextNode.valueOf(outputName + ConvergerComponentConstants.IS_CONVERGED_OUTPUT_SUFFIX));
convergedEndpoint.put(EP_IDENTIFIER, ConvergerComponentConstants.ENDPOINT_ID_AUXILIARY);
convergedEndpoint.put(DATATYPE, TextNode.valueOf(BOOLEAN));
convergedEndpoint.put(IDENTIFIER, TextNode.valueOf(UUID.randomUUID().toString()));
ObjectNode metaData = mapper.createObjectNode();
metaData.put(LOOP_ENDPOINT_TYPE, SELF_LOOP_ENDPOINT);
convergedEndpoint.put(METADATA, metaData);
newOutputEndpoints.add(convergedEndpoint);
}
}
for (JsonNode newOutputEndpoint : newOutputEndpoints) {
((ArrayNode) dynamicOutputs).add(newOutputEndpoint);
}
}
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
description = new PersistentComponentDescription(writer.writeValueAsString(node));
return description;
}
private PersistentComponentDescription updateFrom41To5(PersistentComponentDescription description)
throws JsonProcessingException, IOException {
ObjectMapper mapper = JsonUtils.getDefaultObjectMapper();
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
JsonNode staticOutputs = node.get(STATIC_OUTPUTS);
if (staticOutputs != null) {
for (JsonNode outputEndpoint : staticOutputs) {
ObjectNode metaData;
if (outputEndpoint.has(METADATA)) {
metaData = (ObjectNode) outputEndpoint.get(METADATA);
} else {
metaData = mapper.createObjectNode();
((ObjectNode) outputEndpoint).put(METADATA, metaData);
}
if (outputEndpoint.get(NAME).getTextValue().equals("Outer loop done")) {
metaData.put(LOOP_ENDPOINT_TYPE, "InnerLoopEndpoint");
} else if (outputEndpoint.get(NAME).getTextValue().equals("Converged")) {
metaData.put(LOOP_ENDPOINT_TYPE, OUTER_LOOP_ENDPOINT);
} else if (outputEndpoint.get(NAME).getTextValue().equals("Converged absolute")) {
metaData.put(LOOP_ENDPOINT_TYPE, OUTER_LOOP_ENDPOINT);
} else if (outputEndpoint.get(NAME).getTextValue().equals("Converged relative")) {
metaData.put(LOOP_ENDPOINT_TYPE, OUTER_LOOP_ENDPOINT);
}
}
}
JsonNode dynamicOutputs = node.get(DYNAMIC_OUTPUTS);
if (dynamicOutputs != null) {
for (JsonNode outputEndpoint : dynamicOutputs) {
ObjectNode metaData;
if (outputEndpoint.has(METADATA)) {
metaData = (ObjectNode) outputEndpoint.get(METADATA);
} else {
metaData = mapper.createObjectNode();
((ObjectNode) outputEndpoint).put(METADATA, metaData);
}
// not safe as a "normal" endpoint's name can also end with "_converged"
if (outputEndpoint.get(NAME).getTextValue().endsWith(CONVERGED_SUFFIX)) {
metaData.put(LOOP_ENDPOINT_TYPE, OUTER_LOOP_ENDPOINT);
} else {
metaData.put(LOOP_ENDPOINT_TYPE, SELF_LOOP_ENDPOINT);
}
}
}
JsonNode dynamicInputs = node.get(DYNAMIC_INPUTS);
if (dynamicInputs != null) {
List<JsonNode> startInputs = new ArrayList<>();
for (JsonNode inputEndpoint : dynamicInputs) {
ObjectNode metaData;
if (inputEndpoint.has(METADATA)) {
metaData = (ObjectNode) inputEndpoint.get(METADATA);
} else {
metaData = mapper.createObjectNode();
((ObjectNode) inputEndpoint).put(METADATA, metaData);
}
if (inputEndpoint.get(EP_IDENTIFIER).getTextValue().equals(VALUE_TO_CONVERGE)) {
metaData.put(LOOP_ENDPOINT_TYPE, SELF_LOOP_ENDPOINT);
if (Boolean.valueOf(metaData.get("hasStartValue").asText())) {
continue;
}
ObjectNode startInput = JsonNodeFactory.instance.objectNode();
startInput.put(IDENTIFIER, UUID.randomUUID().toString());
startInput.put(NAME, inputEndpoint.get(NAME).asText() + START_SUFFIX);
startInput.put(EP_IDENTIFIER, VALUE_TO_CONVERGE);
startInput.put("group", "startValues");
startInput.put(DATATYPE, inputEndpoint.get(DATATYPE).asText());
metaData.put(LOOP_ENDPOINT_TYPE, OUTER_LOOP_ENDPOINT);
metaData.put(INPUT_EXECUTION_CONSTRAINT, REQUIRED);
startInput.put(METADATA, metaData);
startInputs.add(startInput);
} else if (inputEndpoint.get(EP_IDENTIFIER).getTextValue().equals(OUTER_LOOP_DONE)) {
metaData.put(LOOP_ENDPOINT_TYPE, OUTER_LOOP_ENDPOINT);
metaData.put(INPUT_EXECUTION_CONSTRAINT, REQUIRED);
}
}
for (JsonNode startInput : startInputs) {
((ArrayNode) dynamicInputs).add(startInput);
}
}
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
PersistentComponentDescription newdesc = new PersistentComponentDescription(writer.writeValueAsString(node));
newdesc.setComponentVersion(V5_0);
return newdesc;
}
private PersistentComponentDescription updateFrom40To41(PersistentComponentDescription description) throws IOException {
ObjectMapper mapper = JsonUtils.getDefaultObjectMapper();
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
JsonNode dynOutputsNode = node.get(DYNAMIC_OUTPUTS);
if (dynOutputsNode != null) {
Iterator<JsonNode> nodeIterator = dynOutputsNode.getElements();
while (nodeIterator.hasNext()) {
ObjectNode dynOutputNode = (ObjectNode) nodeIterator.next();
if (dynOutputNode.get(EP_IDENTIFIER).asText().equals("convergedValue")) {
dynOutputNode.put(EP_IDENTIFIER, ConvergerComponentConstants.ENDPOINT_ID_TO_CONVERGE);
}
}
}
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
description = new PersistentComponentDescription(writer.writeValueAsString(node));
description.setComponentVersion(V4_1);
return description;
}
private PersistentComponentDescription updateFrom32To40(PersistentComponentDescription description)
throws JsonProcessingException, IOException {
ObjectMapper mapper = JsonUtils.getDefaultObjectMapper();
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
ObjectNode configNode = (ObjectNode) node.get(CONFIGURATION);
JsonNode maxIterNode = configNode.get("maxIterations");
if (maxIterNode != null) {
String maxConvChecks = maxIterNode.getTextValue();
configNode.remove("maxIterations");
configNode.put(ConvergerComponentConstants.KEY_MAX_CONV_CHECKS, maxConvChecks);
}
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
description = new PersistentComponentDescription(writer.writeValueAsString(node));
description.setComponentVersion(V4_0);
return description;
}
private PersistentComponentDescription updateFrom31To32(PersistentComponentDescription description)
throws JsonParseException, IOException {
description = PersistentComponentDescriptionUpdaterUtils.updateIsNestedLoop(description);
ObjectMapper mapper = JsonUtils.getDefaultObjectMapper();
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
JsonNode dynInputsNode = node.get(DYNAMIC_INPUTS);
if (dynInputsNode != null) {
Iterator<JsonNode> nodeIterator = dynInputsNode.getElements();
while (nodeIterator.hasNext()) {
JsonNode dynInputNode = nodeIterator.next();
ObjectNode jsonNode = (ObjectNode) dynInputNode.get(METADATA);
JsonNode hasStartValueJsonNode = jsonNode.get("hasStartValue");
if (hasStartValueJsonNode != null) {
String hasStartValue = hasStartValueJsonNode.getTextValue();
if (hasStartValue.equals("true")) {
FloatTD floatValue = typedDatumService.getFactory()
.createFloat(Double.valueOf(jsonNode.get("startValue").getTextValue()));
jsonNode.put("initValue_dca67e34", typedDatumService.getSerializer().serialize(floatValue));
}
}
}
}
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
description = new PersistentComponentDescription(writer.writeValueAsString(node));
description.setComponentVersion(V3_2);
return description;
}
/**
* Updates descriptions of version 3.0 to 3.1.
**/
private PersistentComponentDescription updateFrom30To31(PersistentComponentDescription description)
throws JsonParseException, IOException {
ObjectMapper mapper = JsonUtils.getDefaultObjectMapper();
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
ObjectNode objectNode = (ObjectNode) node.get(CONFIGURATION);
objectNode.put(ConvergerComponentConstants.KEY_ITERATIONS_TO_CONSIDER, "1");
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
description = new PersistentComponentDescription(writer.writeValueAsString(node));
description.setComponentVersion(V3_1);
return description;
}
/**
* The second update is for the Workflow update 3.0, and though for versions between 1.0 and 3.0. It updates the IDs for the dynamic in
* and outputs.
*/
private PersistentComponentDescription secondUpdate(PersistentComponentDescription description) throws JsonParseException, IOException {
ObjectMapper mapper = JsonUtils.getDefaultObjectMapper();
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
JsonNode dynInputs = node.get(DYNAMIC_INPUTS);
if (dynInputs != null) {
for (JsonNode inputEndpoint : dynInputs) {
if (inputEndpoint.get(EP_IDENTIFIER).isNull()) {
((ObjectNode) inputEndpoint).remove(EP_IDENTIFIER);
if (inputEndpoint.get(DATATYPE).getTextValue().equals("Float")) {
((ObjectNode) inputEndpoint).put(EP_IDENTIFIER, TextNode.valueOf(
ConvergerComponentConstants.ENDPOINT_ID_TO_CONVERGE));
} else {
((ObjectNode) inputEndpoint).put(EP_IDENTIFIER, TextNode.valueOf(OUTER_LOOP_DONE));
}
}
}
}
JsonNode dynOutputs = node.get(DYNAMIC_OUTPUTS);
if (dynOutputs != null) {
for (JsonNode outputEndpoint : dynOutputs) {
((ObjectNode) outputEndpoint).remove(EP_IDENTIFIER);
if (outputEndpoint.get(EP_IDENTIFIER) == null) {
((ObjectNode) outputEndpoint).put(EP_IDENTIFIER, TextNode.valueOf(ConvergerComponentConstants.ENDPOINT_ID_TO_CONVERGE));
}
}
}
ArrayNode statOutputs = (ArrayNode) node.get(STATIC_OUTPUTS);
if (statOutputs == null) {
statOutputs = JsonNodeFactory.instance.arrayNode();
ObjectNode outputEndpoint = JsonNodeFactory.instance.objectNode();
outputEndpoint.put(NAME, TextNode.valueOf("Converged"));
outputEndpoint.put(DATATYPE, TextNode.valueOf(BOOLEAN));
outputEndpoint.put(IDENTIFIER, TextNode.valueOf(UUID.randomUUID().toString()));
statOutputs.add(outputEndpoint);
outputEndpoint = JsonNodeFactory.instance.objectNode();
outputEndpoint.put(NAME, TextNode.valueOf("Converged absolute"));
outputEndpoint.put(DATATYPE, TextNode.valueOf(BOOLEAN));
outputEndpoint.put(IDENTIFIER, TextNode.valueOf(UUID.randomUUID().toString()));
statOutputs.add(outputEndpoint);
outputEndpoint = JsonNodeFactory.instance.objectNode();
outputEndpoint.put(NAME, TextNode.valueOf("Converged relative"));
outputEndpoint.put(DATATYPE, TextNode.valueOf(BOOLEAN));
outputEndpoint.put(IDENTIFIER, TextNode.valueOf(UUID.randomUUID().toString()));
statOutputs.add(outputEndpoint);
((ObjectNode) node).put(STATIC_OUTPUTS, statOutputs);
}
ArrayNode statInputs = (ArrayNode) node.get(STATIC_INPUTS);
if (statInputs == null) {
statInputs = JsonNodeFactory.instance.arrayNode();
ObjectNode inputEndpoint = JsonNodeFactory.instance.objectNode();
inputEndpoint.put(NAME, TextNode.valueOf(OUTER_LOOP_DONE));
inputEndpoint.put(DATATYPE, TextNode.valueOf(BOOLEAN));
inputEndpoint.put(IDENTIFIER, TextNode.valueOf(UUID.randomUUID().toString()));
inputEndpoint.put("readonly", "true");
ObjectNode metadata = JsonNodeFactory.instance.objectNode();
metadata.put("usage", "optional");
inputEndpoint.put(METADATA, metadata);
statInputs.add(inputEndpoint);
}
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
description = new PersistentComponentDescription(writer.writeValueAsString(node));
description =
PersistentComponentDescriptionUpdaterUtils.updateAllDynamicEndpointsToIdentifier("dynamicOutputs",
ConvergerComponentConstants.ENDPOINT_ID_TO_CONVERGE, description);
return description;
}
/**
* The first update is for Componentversions < 1.0 and updates the eps configuration from Double to String. It further adds new output
* channel that were needed.
*/
private PersistentComponentDescription firstUpdate(PersistentComponentDescription description) throws IOException, JsonParseException,
JsonProcessingException, JsonGenerationException, JsonMappingException {
ObjectMapper mapper = JsonUtils.getDefaultObjectMapper();
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
description = replaceEpsDataType(mapper, node, "epsR");
description = replaceEpsDataType(mapper, node, "epsA");
description = addConvergedOutputs(mapper, node);
return description;
}
private PersistentComponentDescription replaceEpsDataType(ObjectMapper mapper, JsonNode node, String eps)
throws JsonParseException, IOException, JsonGenerationException, JsonMappingException {
PersistentComponentDescription description;
// TODO actually constants from DescriptionWorkflowPersistenceHandler must be used. but they
// must be moved to
// core.component beforehand to prohibit bad dependencies
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
ArrayNode configurationNode = (ArrayNode) node.get(CONFIGURATION);
ArrayNode newConfigurationNode = JsonNodeFactory.instance.arrayNode();
JsonNode oldEpsNode = null;
for (JsonNode n : configurationNode) {
if (n.getTextValue().startsWith(eps + ":java.lang.Double:")) {
oldEpsNode = n;
} else {
newConfigurationNode.add(n);
}
}
if (oldEpsNode != null) {
String nodeString = oldEpsNode.getTextValue();
String value = "";
if (nodeString.split(COLON).length > 1) {
value = nodeString.split(COLON)[2];
}
newConfigurationNode.add(TextNode.valueOf(eps + ":java.lang.String:" + value));
((ObjectNode) node).remove(CONFIGURATION);
((ObjectNode) node).put(CONFIGURATION, newConfigurationNode);
}
description = new PersistentComponentDescription(writer.writeValueAsString(node));
return description;
}
private PersistentComponentDescription addConvergedOutputs(ObjectMapper mapper, JsonNode node) throws JsonParseException,
JsonGenerationException, JsonMappingException, IOException {
PersistentComponentDescription description;
// TODO actually constants from DescriptionWorkflowPersistenceHandler must be used. but they
// must be moved to
// core.component beforehand to prohibit bad dependencies
JsonNode addOutputNode = node.get("addOutput");
Map<String, String> outputs = getOutputs(addOutputNode);
setOutputs(addOutputNode, outputs);
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
description = new PersistentComponentDescription(writer.writeValueAsString(node));
return description;
}
private Map<String, String> getOutputs(JsonNode addOutputNode) {
Map<String, String> outputs = new HashMap<String, String>();
Iterator<JsonNode> nodeIterator = addOutputNode.getElements();
while (nodeIterator.hasNext()) {
String[] output = nodeIterator.next().getTextValue().split(COLON);
outputs.put(output[0], output[1]);
}
return outputs;
}
private JsonNode setOutputs(JsonNode addOutputNode, Map<String, String> outputs) {
((ArrayNode) addOutputNode).removeAll();
for (String outputName : outputs.keySet()) {
((ArrayNode) addOutputNode).add(outputName + COLON + outputs.get(outputName));
if (!outputName.endsWith(ConvergerComponentConstants.CONVERGED_OUTPUT_SUFFIX)
&& !outputs.containsKey(outputName + ConvergerComponentConstants.CONVERGED_OUTPUT_SUFFIX)) {
((ArrayNode) addOutputNode).add(outputName
+ ConvergerComponentConstants.CONVERGED_OUTPUT_SUFFIX + COLON + outputs.get(outputName));
}
}
return addOutputNode;
}
protected void bindTypedDatumService(TypedDatumService newService) {
typedDatumService = newService;
}
}