/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.core.component.update.api;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.UUID;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonParser;
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.core.component.api.ComponentConstants;
import de.rcenvironment.core.component.api.LoopComponentConstants;
import de.rcenvironment.core.component.model.endpoint.api.EndpointDefinition;
import de.rcenvironment.core.utils.common.JsonUtils;
/**
* Utils for updater classes.
*
* @author Sascha Zur
* @author Doreen Seider
* @author Markus Kunde
*/
public final class PersistentComponentDescriptionUpdaterUtils {
/** json key. */
public static final String EP_IDENTIFIER = "epIdentifier";
private static final String INITIAL = "initial";
private static final String REQUIRED = "required";
private static final String CONFIGURATION = "configuration";
private static final String USAGE = "usage";
private static final String NAME = "name";
private static final String STATIC_OUTPUTS = "staticOutputs";
private static final String STATIC_INPUTS = "staticInputs";
private static final String DYNAMIC_INPUTS = "dynamicInputs";
private static final String DYNAMIC_OUTPUTS = "dynamicOutputs";
private static final String METADATA = "metadata";
private static final String DIRECTORY = "Directory";
private static final String DATATYPE = "datatype";
private static final String IDENTIFIER = "identifier";
private static ObjectMapper mapper = JsonUtils.getDefaultObjectMapper();
private PersistentComponentDescriptionUpdaterUtils() {}
/**
* @param direction if it is in or outputs (valid are "dynmaicInputs" and "dynamicOutputs")
* @param identifier that shall be used
* @param description of the component
* @return updated description
* @throws JsonParseException :
* @throws IOException :
*/
public static PersistentComponentDescription updateAllDynamicEndpointsToIdentifier(String direction, String identifier,
PersistentComponentDescription description) throws JsonParseException, IOException {
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
JsonNode dynEndpoints = node.get(direction);
if (dynEndpoints != null) {
for (JsonNode endpoint : dynEndpoints) {
if (endpoint.get(EP_IDENTIFIER) == null || endpoint.get(EP_IDENTIFIER).equals("null")
|| endpoint.get(EP_IDENTIFIER).isNull()) {
((ObjectNode) endpoint).remove(EP_IDENTIFIER);
((ObjectNode) endpoint).put(EP_IDENTIFIER, TextNode.valueOf(identifier));
}
}
}
// Add Static endpoints
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
return new PersistentComponentDescription(writer.writeValueAsString(node));
}
/**
* Removes endpoints related to "outer loop done" approach. (RCE 7.1.2 -> 8.0.0).
*
* @param description {@link PersistentComponentDescription} to update
* @return updated {@link PersistentComponentDescription}
* @throws JsonProcessingException on unexpected error
* @throws IOException on unexpected error
*/
public static PersistentComponentDescription removeOuterLoopDoneEndpoints(PersistentComponentDescription description)
throws JsonProcessingException, IOException {
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
removeOuterLoopDoneEndpoint(node, STATIC_OUTPUTS, NAME, "Outer loop done");
removeOuterLoopDoneEndpoint(node, DYNAMIC_INPUTS, EP_IDENTIFIER, "outerLoopDone");
return new PersistentComponentDescription(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(node));
}
private static void removeOuterLoopDoneEndpoint(JsonNode node, String endpointGroup, String identifyingKey, String identifyingValue) {
if (node.has(endpointGroup)) {
ArrayNode endpointsJsonNode = (ArrayNode) node.get(endpointGroup);
Iterator<JsonNode> elements = endpointsJsonNode.getElements();
while (elements.hasNext()) {
ObjectNode endpointJsonNode = (ObjectNode) elements.next();
if (endpointJsonNode.get(identifyingKey).getTextValue().equals(identifyingValue)) {
elements.remove();
break;
}
}
}
}
/**
* Removes endpoint character information from meta data. (RCE 7.1.2 -> 8.0.0).
*
* @param description {@link PersistentComponentDescription} to update
* @return updated {@link PersistentComponentDescription}
* @throws JsonProcessingException on unexpected error
* @throws IOException on unexpected error
*/
public static PersistentComponentDescription removeEndpointCharacterInfoFromMetaData(PersistentComponentDescription description)
throws JsonProcessingException, IOException {
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
removeEndpointCharacterInfoFromMetaData(node, STATIC_INPUTS);
removeEndpointCharacterInfoFromMetaData(node, STATIC_OUTPUTS);
removeEndpointCharacterInfoFromMetaData(node, DYNAMIC_INPUTS);
removeEndpointCharacterInfoFromMetaData(node, DYNAMIC_OUTPUTS);
return new PersistentComponentDescription(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(node));
}
private static void removeEndpointCharacterInfoFromMetaData(JsonNode node, String endpointGroup) {
if (node.has(endpointGroup)) {
ArrayNode endpointsJsonNode = (ArrayNode) node.get(endpointGroup);
Iterator<JsonNode> elements = endpointsJsonNode.getElements();
while (elements.hasNext()) {
JsonNode endpointJsonNode = elements.next();
if (endpointJsonNode.has(METADATA)) {
JsonNode metaDataJsonNode = endpointJsonNode.get(METADATA);
Iterator<Entry<String, JsonNode>> metaDataFields = metaDataJsonNode.getFields();
while (metaDataFields.hasNext()) {
Entry<String, JsonNode> nextMetaDataField = metaDataFields.next();
if (nextMetaDataField.getKey().equals("loopEndpointType_5e0ed1cd")) {
metaDataFields.remove();
break;
}
}
}
}
}
}
/**
* Reassigns new endpoint identifiers for certain entdpoints. (RCE 7.1.2 -> 8.0.0).
*
* @param description {@link PersistentComponentDescription} to update
* @param endpointGroup e.g. "staticInputs", "dynamicOutputs", etc.
* @param epIdentifier identifier of the endpoint of request
* @param epIdentifierToReplace new identifier of endpoint
* @param epNameSuffix name suffix of endpoint of request
* @return updated {@link PersistentComponentDescription}
* @throws JsonProcessingException on unexpected error
* @throws IOException on unexpected error
*/
public static PersistentComponentDescription reassignEndpointIdentifiers(PersistentComponentDescription description,
String endpointGroup, String epIdentifier, String epIdentifierToReplace, String epNameSuffix)
throws JsonProcessingException, IOException {
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
if (node.has(endpointGroup)) {
ArrayNode endpointsJsonNode = (ArrayNode) node.get(endpointGroup);
Iterator<JsonNode> elements = endpointsJsonNode.getElements();
while (elements.hasNext()) {
JsonNode endpointJsonNode = elements.next();
if (endpointJsonNode.has(EP_IDENTIFIER)) {
if (endpointJsonNode.get(EP_IDENTIFIER).getTextValue().equals(epIdentifier)
&& endpointJsonNode.get(NAME).getTextValue().endsWith(epNameSuffix)) {
((ObjectNode) endpointJsonNode).put(EP_IDENTIFIER, epIdentifierToReplace);
}
}
}
}
return new PersistentComponentDescription(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(node));
}
/**
* Updates configuration key for fault-tolerance (RCE 7.0.2 -> 7.1.0).
*
* @param description {@link PersistentComponentDescription} to update
* @return updated {@link PersistentComponentDescription}
* @throws JsonProcessingException on unexpected error
* @throws IOException on unexpected error
*/
public static PersistentComponentDescription updateFaultToleranceOfLoopDriver(PersistentComponentDescription description)
throws JsonProcessingException, IOException {
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
JsonNode configJsonNode = node.get("configuration");
if (configJsonNode instanceof ObjectNode) {
ObjectNode configObjectNode = (ObjectNode) configJsonNode;
String confgKeyFaultToleranceNAV = "loopFaultTolerance_5e0ed1cd";
if (configObjectNode.has(confgKeyFaultToleranceNAV)) {
String faultToleranceNAV = configObjectNode.get(confgKeyFaultToleranceNAV).getTextValue();
configObjectNode.put(confgKeyFaultToleranceNAV, "Fail");
configObjectNode.put("faultTolerance-NAV_5e0ed1cd", faultToleranceNAV);
}
String configKeyMaxRerunBeforeFail = "loopRerunAndFail_5e0ed1cd";
if (configObjectNode.has(configKeyMaxRerunBeforeFail)) {
String faultToleranceNAV = configObjectNode.get(configKeyMaxRerunBeforeFail).getTextValue();
configObjectNode.remove(configKeyMaxRerunBeforeFail);
configObjectNode.put("maxRerunBeforeFail-NAV_5e0ed1cd", faultToleranceNAV);
}
String configKeyMaxRerunBeforeDiscard = "loopRerunAndDiscard_5e0ed1cd";
if (configObjectNode.has(configKeyMaxRerunBeforeDiscard)) {
String faultToleranceNAV = configObjectNode.get(configKeyMaxRerunBeforeDiscard).getTextValue();
configObjectNode.remove(configKeyMaxRerunBeforeDiscard);
configObjectNode.put("maxRerunBeforeDiscard-NAV_5e0ed1cd", faultToleranceNAV);
}
String configKeyFailLoopOnly = "failLoop_5e0ed1cd";
if (configObjectNode.has(configKeyFailLoopOnly)) {
String faultToleranceNAV = configObjectNode.get(configKeyFailLoopOnly).getTextValue();
configObjectNode.remove(configKeyFailLoopOnly);
configObjectNode.put("failLoopOnly-NAV_5e0ed1cd", faultToleranceNAV);
}
String configKeyFinallyFailIfDiscarded = "finallyFail_5e0ed1cd";
if (configObjectNode.has(configKeyFinallyFailIfDiscarded)) {
String faultToleranceNAV = configObjectNode.get(configKeyFinallyFailIfDiscarded).getTextValue();
configObjectNode.remove(configKeyFinallyFailIfDiscarded);
configObjectNode.put("finallyFailIfDiscarded-NAV_5e0ed1cd", faultToleranceNAV);
}
}
return new PersistentComponentDescription(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(node));
}
/**
* Replaces the usage meta data entries with input handling and input execution constraints entries.
*
* @param description {@link PersistentComponentDescription} of the component
* @return {@link PersistentComponentDescription} with updated scheduling information
* @throws JsonParseException on error
* @throws IOException on error
*/
public static PersistentComponentDescription updateSchedulingInformation(PersistentComponentDescription description)
throws JsonParseException, IOException {
JsonFactory jsonFactory = new JsonFactory();
JsonParser jsonParser = jsonFactory.createJsonParser(description.getComponentDescriptionAsString());
JsonNode node = mapper.readTree(jsonParser);
jsonParser.close();
updateInputNode(node.get(DYNAMIC_INPUTS));
updateInputNode(node.get(STATIC_INPUTS));
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
description = new PersistentComponentDescription(writer.writeValueAsString(node));
return description;
}
/**
* Updates the configuration key for "is nested loop".
*
* @param description {@link PersistentComponentDescription} of the component
* @return {@link PersistentComponentDescription} with updated scheduling information
* @throws JsonParseException on error
* @throws IOException on error
*/
public static PersistentComponentDescription updateIsNestedLoop(PersistentComponentDescription description)
throws JsonParseException, IOException {
JsonFactory jsonFactory = new JsonFactory();
JsonParser jsonParser = jsonFactory.createJsonParser(description.getComponentDescriptionAsString());
JsonNode node = mapper.readTree(jsonParser);
jsonParser.close();
String oldConfigKey = "isNestedLoop";
ObjectNode configurationsNode = (ObjectNode) node.get(CONFIGURATION);
if (configurationsNode != null && configurationsNode.has(oldConfigKey)) {
boolean isNestedLoop = configurationsNode.get(oldConfigKey).asBoolean();
configurationsNode.remove(oldConfigKey);
configurationsNode.put(LoopComponentConstants.CONFIG_KEY_IS_NESTED_LOOP, isNestedLoop);
}
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
description = new PersistentComponentDescription(writer.writeValueAsString(node));
return description;
}
private static void updateInputNode(JsonNode inputNode) {
if (inputNode != null) {
Iterator<JsonNode> nodeIterator = inputNode.getElements();
while (nodeIterator.hasNext()) {
JsonNode dynInputNode = nodeIterator.next();
ObjectNode jsonNode = (ObjectNode) dynInputNode.get(METADATA);
JsonNode usageJsonNode = jsonNode.get(USAGE);
if (usageJsonNode != null) {
String usage = usageJsonNode.getTextValue();
switch (usage) {
case REQUIRED:
jsonNode.put(ComponentConstants.INPUT_METADATA_KEY_INPUT_DATUM_HANDLING,
EndpointDefinition.InputDatumHandling.Single.name());
jsonNode.put(ComponentConstants.INPUT_METADATA_KEY_INPUT_EXECUTION_CONSTRAINT,
EndpointDefinition.InputExecutionContraint.Required.name());
break;
case INITIAL:
jsonNode.put(ComponentConstants.INPUT_METADATA_KEY_INPUT_DATUM_HANDLING,
EndpointDefinition.InputDatumHandling.Constant.name());
jsonNode.put(ComponentConstants.INPUT_METADATA_KEY_INPUT_EXECUTION_CONSTRAINT,
EndpointDefinition.InputExecutionContraint.Required.name());
break;
case "optional":
jsonNode.put(ComponentConstants.INPUT_METADATA_KEY_INPUT_DATUM_HANDLING,
EndpointDefinition.InputDatumHandling.Single.name());
jsonNode.put(ComponentConstants.INPUT_METADATA_KEY_INPUT_EXECUTION_CONSTRAINT,
EndpointDefinition.InputExecutionContraint.NotRequired.name());
break;
default:
break;
}
jsonNode.remove(USAGE);
}
}
}
}
/**
* Adding staticInput "CPACS".
*
* @param description of the component
* @param inputName name of the static input to add
* @return updated description
* @throws JsonParseException thrown on an error
* @throws JsonGenerationException thrown on an error
* @throws JsonMappingException thrown on an error
* @throws IOException thrown on an error
*/
public static PersistentComponentDescription addStaticInput(PersistentComponentDescription description, String inputName)
throws JsonParseException, JsonGenerationException, JsonMappingException, IOException {
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
ArrayNode staticInputs = (ArrayNode) node.get(STATIC_INPUTS);
if (staticInputs == null) {
staticInputs = JsonNodeFactory.instance.arrayNode();
((ObjectNode) node).put(STATIC_INPUTS, staticInputs);
}
ObjectNode staticCPACSIn = JsonNodeFactory.instance.objectNode();
ObjectNode metaDataNode = JsonNodeFactory.instance.objectNode();
metaDataNode.put(USAGE, TextNode.valueOf(INITIAL));
staticCPACSIn.put(NAME, TextNode.valueOf(inputName));
staticCPACSIn.put(DATATYPE, TextNode.valueOf("FileReference"));
staticCPACSIn.put(METADATA, metaDataNode);
staticCPACSIn.put(IDENTIFIER, TextNode.valueOf(UUID.randomUUID().toString()));
staticInputs.add(staticCPACSIn);
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
return new PersistentComponentDescription(writer.writeValueAsString(node));
}
/**
*
* Adds a static output.
*
* @param description to change
* @param outputName of the output to add
* @param dataType of the output to add
* @return PersistentComponentDescription with added output
* @throws JsonParseException thrown on an error
* @throws JsonGenerationException thrown on an error
* @throws JsonMappingException thrown on an error
* @throws IOException thrown on an error
*/
public static PersistentComponentDescription addStaticOutput(PersistentComponentDescription description, String outputName,
String dataType) throws JsonParseException, JsonGenerationException, JsonMappingException, IOException {
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
ArrayNode staticOutputs = (ArrayNode) node.get(STATIC_OUTPUTS);
if (staticOutputs == null) {
staticOutputs = JsonNodeFactory.instance.arrayNode();
((ObjectNode) node).put(STATIC_OUTPUTS, staticOutputs);
}
ObjectNode newOutput = JsonNodeFactory.instance.objectNode();
newOutput.put(NAME, TextNode.valueOf(outputName));
newOutput.put(DATATYPE, TextNode.valueOf(dataType));
newOutput.put(METADATA, JsonNodeFactory.instance.objectNode());
newOutput.put(IDENTIFIER, TextNode.valueOf(UUID.randomUUID().toString()));
staticOutputs.add(newOutput);
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
return new PersistentComponentDescription(writer.writeValueAsString(node));
}
/**
* Adding staticOutput "CPACS".
*
* @param description of the component
* @param outputName name of the static output to add
* @return updated description
* @throws JsonParseException thrown on an error
* @throws JsonGenerationException thrown on an error
* @throws JsonMappingException thrown on an error
* @throws IOException thrown on an error
*/
public static PersistentComponentDescription addStaticOutput(PersistentComponentDescription description, String outputName)
throws JsonParseException, JsonGenerationException, JsonMappingException, IOException {
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
ArrayNode staticOutputs = (ArrayNode) node.get(STATIC_OUTPUTS);
if (staticOutputs == null) {
staticOutputs = JsonNodeFactory.instance.arrayNode();
((ObjectNode) node).put(STATIC_OUTPUTS, staticOutputs);
}
ObjectNode staticCPACSOut = JsonNodeFactory.instance.objectNode();
staticCPACSOut.put(NAME, TextNode.valueOf(outputName));
staticCPACSOut.put(DATATYPE, TextNode.valueOf("FileReference"));
staticCPACSOut.put(METADATA, JsonNodeFactory.instance.objectNode());
staticCPACSOut.put(IDENTIFIER, TextNode.valueOf(UUID.randomUUID().toString()));
staticOutputs.add(staticCPACSOut);
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
return new PersistentComponentDescription(writer.writeValueAsString(node));
}
/**
* Updating "consumeCPACS" flag.
*
* @param description of the component
* @return updated description
* @throws JsonParseException thrown on an error
* @throws JsonGenerationException thrown on an error
* @throws JsonMappingException thrown on an error
* @throws IOException thrown on an error
*/
// This method is CPACS-specific and thus, this bundle is not the correct place for it. But it is not feasible to create a new bundle
// for just that method.
public static PersistentComponentDescription updateConsumeCPACSFlag(PersistentComponentDescription description)
throws JsonParseException, JsonGenerationException, JsonMappingException, IOException {
final String consumeCPACSInputsConfigVersion3 = "consumeCPACS";
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
ArrayNode staticInputs = (ArrayNode) node.get(STATIC_INPUTS);
ObjectNode configuration = (ObjectNode) node.get(CONFIGURATION);
if (configuration.get(consumeCPACSInputsConfigVersion3) != null
&& Boolean.valueOf(configuration.get(consumeCPACSInputsConfigVersion3).getTextValue())) {
for (JsonNode staticInput : staticInputs) {
if (!(staticInput.get(NAME).getTextValue().equals(DIRECTORY))) {
ObjectNode metadata = (ObjectNode) staticInput.get(METADATA);
metadata.put(USAGE, TextNode.valueOf(REQUIRED));
}
}
}
configuration.remove(consumeCPACSInputsConfigVersion3);
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
return new PersistentComponentDescription(writer.writeValueAsString(node));
}
/**
* Sets all dynamic input channels usage to "optional".
*
* @param description of the component
* @return updated description
* @throws JsonParseException thrown on an error
* @throws JsonGenerationException thrown on an error
* @throws JsonMappingException thrown on an error
* @throws IOException thrown on an error
*/
public static PersistentComponentDescription updateDynamicInputsOptional(PersistentComponentDescription description)
throws JsonParseException, JsonGenerationException, JsonMappingException, IOException {
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
ArrayNode dynamicInputs = (ArrayNode) node.get(DYNAMIC_INPUTS);
if (dynamicInputs != null) {
for (JsonNode dynamicInput : dynamicInputs) {
if (!(dynamicInput.get(NAME).getTextValue().equals(DIRECTORY))) {
((ObjectNode) dynamicInput.get(METADATA)).put(USAGE, TextNode.valueOf("optional"));
}
}
}
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
return new PersistentComponentDescription(writer.writeValueAsString(node));
}
/**
* Updating "consumeDirectory" flag.
*
* @param description of the component
* @return updated description
* @throws JsonParseException thrown on an error
* @throws JsonGenerationException thrown on an error
* @throws JsonMappingException thrown on an error
* @throws IOException thrown on an error
*/
public static PersistentComponentDescription updateConsumeDirectoryFlag(PersistentComponentDescription description)
throws JsonParseException, JsonGenerationException, JsonMappingException, IOException {
final String consumeDirectoryInputsConfigVersion3 = "consumeDirectory";
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
ArrayNode dynamicInputs = (ArrayNode) node.get(DYNAMIC_INPUTS);
ObjectNode configuration = (ObjectNode) node.get(CONFIGURATION);
if (configuration.get(consumeDirectoryInputsConfigVersion3) != null
&& Boolean.valueOf(configuration.get(consumeDirectoryInputsConfigVersion3).getTextValue())) {
for (JsonNode dynamicInput : dynamicInputs) {
if (dynamicInput.get(NAME).getTextValue().equals(DIRECTORY)) {
ObjectNode metadata = (ObjectNode) dynamicInput.get(METADATA);
metadata.put(USAGE, TextNode.valueOf(REQUIRED));
}
}
} else if (configuration.get(consumeDirectoryInputsConfigVersion3) != null
&& !configuration.get(consumeDirectoryInputsConfigVersion3).getBooleanValue()) {
for (JsonNode dynamicInput : dynamicInputs) {
if (dynamicInput.get(NAME).getTextValue().equals(DIRECTORY)) {
ObjectNode metadata = (ObjectNode) dynamicInput.get(METADATA);
metadata.put(USAGE, TextNode.valueOf(INITIAL));
}
}
}
configuration.remove(consumeDirectoryInputsConfigVersion3);
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
return new PersistentComponentDescription(writer.writeValueAsString(node));
}
/**
* Updating Directory channel to id "directory".
*
* @param direction if it is in or outputs (valid are "dynamicInputs" and "dynamicOutputs")
* @param description of the component
* @return updated description
* @throws JsonParseException thrown on an error
* @throws JsonGenerationException thrown on an error
* @throws JsonMappingException thrown on an error
* @throws IOException thrown on an error
*/
public static PersistentComponentDescription updateDirectoryEndpointId(String direction, PersistentComponentDescription description)
throws JsonParseException, JsonGenerationException, JsonMappingException, IOException {
JsonNode node = mapper.readTree(description.getComponentDescriptionAsString());
JsonNode dynEndpoints = node.get(direction);
if (dynEndpoints != null) {
for (JsonNode endpoint : dynEndpoints) {
if (endpoint.get(NAME).getTextValue().equals(DIRECTORY)) {
((ObjectNode) endpoint).remove(EP_IDENTIFIER);
((ObjectNode) endpoint).put(EP_IDENTIFIER, TextNode.valueOf("directory"));
}
}
}
// Add Static endpoints
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
return new PersistentComponentDescription(writer.writeValueAsString(node));
}
}