/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.components.optimizer.gui.properties.commands;
import java.util.HashMap;
import java.util.Map;
import de.rcenvironment.components.optimizer.common.OptimizerComponentConstants;
import de.rcenvironment.core.component.api.ComponentConstants;
import de.rcenvironment.core.component.model.endpoint.api.EndpointDefinition;
import de.rcenvironment.core.component.model.endpoint.api.EndpointDescription;
import de.rcenvironment.core.component.workflow.model.api.WorkflowNode;
import de.rcenvironment.core.datamodel.api.EndpointType;
import de.rcenvironment.core.gui.workflow.editor.commands.endpoint.EditDynamicEndpointCommand;
import de.rcenvironment.core.gui.workflow.editor.properties.Refreshable;
/**
* Command for editing an endpoint in the optimizer component.
*
* @author Sascha Zur
*/
public class OptimizerEditDynamicEndpointCommand extends EditDynamicEndpointCommand {
private static final String DESIGN_VARIABLE = "Design";
private static final String DASH = "-";
public OptimizerEditDynamicEndpointCommand(EndpointType direction, String id, EndpointDescription oldDescription,
EndpointDescription newDescription, boolean executable, boolean undoable, Refreshable... refreshable) {
super(direction, oldDescription, newDescription, refreshable);
}
@Override
public void execute() {
final WorkflowNode workflowNode = getWorkflowNode();
super.execute();
switch (direction) {
case INPUT:
if (hasGradient(oldDesc)) {
if (hasGradient(newDesc)) {
executeBothHaveGradients(workflowNode);
} else {
for (EndpointDescription variable : workflowNode.getOutputDescriptionsManager().getDynamicEndpointDescriptions()) {
if (variable.getDynamicEndpointIdentifier().equals(DESIGN_VARIABLE)) {
String oldGradientName =
OptimizerDynamicEndpointCommandHelper.createGradientChannelName(oldDesc.getName(), variable.getName());
workflowNode.getInputDescriptionsManager().removeDynamicEndpointDescription(oldGradientName);
}
}
}
} else {
if (hasGradient(newDesc)) {
for (EndpointDescription variable : workflowNode.getOutputDescriptionsManager().getDynamicEndpointDescriptions()) {
if (variable.getDynamicEndpointIdentifier().equals(DESIGN_VARIABLE)) {
String newGradientName =
OptimizerDynamicEndpointCommandHelper.createGradientChannelName(newDesc.getName(), variable.getName());
Map<String, String> metaData = new HashMap<>();
for (String key : newDesc.getMetaData().keySet()) {
if (key.equals(OptimizerComponentConstants.METADATA_VECTOR_SIZE)
|| key.startsWith(ComponentConstants.INPUT_METADATA_KEY_INPUT_DATUM_HANDLING)
|| key.startsWith(ComponentConstants.INPUT_METADATA_KEY_INPUT_EXECUTION_CONSTRAINT)) {
metaData.put(key, newDesc.getMetaData().get(key));
} else {
metaData.put(key, DASH);
}
}
workflowNode.getInputDescriptionsManager().addDynamicEndpointDescription(
OptimizerComponentConstants.ID_GRADIENTS, newGradientName,
variable.getDataType(), metaData);
}
}
}
}
break;
case OUTPUT:
if (!newDesc.getName().equals(oldDesc.getName()) || !newDesc.getDataType().equals(oldDesc.getDataType())) {
for (EndpointDescription function : workflowNode.getInputDescriptionsManager().getDynamicEndpointDescriptions()) {
if (!workflowNode.getInputDescriptionsManager().isValidEndpointName(
OptimizerDynamicEndpointCommandHelper.createGradientChannelName(function.getName(), oldDesc.getName()))) {
String oldName =
OptimizerDynamicEndpointCommandHelper.createGradientChannelName(function.getName(), oldDesc.getName());
String newName =
OptimizerDynamicEndpointCommandHelper.createGradientChannelName(function.getName(), newDesc.getName());
EndpointDescription desc = workflowNode.getInputDescriptionsManager().getEndpointDescription(
OptimizerDynamicEndpointCommandHelper.createGradientChannelName(function.getName(), oldDesc.getName()));
desc.setName(newName);
workflowNode.getInputDescriptionsManager().editDynamicEndpointDescription(oldName, newName, newDesc.getDataType(),
desc.getMetaData());
}
}
}
if (!oldDesc.getName().equals(newDesc.getName()) || !oldDesc.getDataType().equals(newDesc.getDataType())) {
if (getWorkflowNode().getOutputDescriptionsManager().getEndpointDescription(
oldDesc.getName() + OptimizerComponentConstants.OPTIMUM_VARIABLE_SUFFIX) != null) {
getWorkflowNode().getOutputDescriptionsManager().removeDynamicEndpointDescription(
oldDesc.getName() + OptimizerComponentConstants.OPTIMUM_VARIABLE_SUFFIX);
}
Map<String, String> metadata = new HashMap<>();
metadata.putAll(newDesc.getMetaData());
getWorkflowNode().getOutputDescriptionsManager().addDynamicEndpointDescription(OptimizerComponentConstants.ID_OPTIMA,
newDesc.getName() + OptimizerComponentConstants.OPTIMUM_VARIABLE_SUFFIX,
newDesc.getDataType(), metadata);
}
handleExtraValueInputs(workflowNode, OptimizerComponentConstants.META_HAS_STARTVALUE,
null, OptimizerComponentConstants.STARTVALUE_SIGNATURE, true, oldDesc, newDesc);
handleExtraValueInputs(workflowNode, OptimizerComponentConstants.META_USE_STEP,
OptimizerComponentConstants.META_USE_UNIFIED_STEP, OptimizerComponentConstants.STEP_VALUE_SIGNATURE, false, oldDesc,
newDesc);
break;
default:
throw new RuntimeException();
}
String oldHasBounds = oldDesc.getMetaDataValue(OptimizerComponentConstants.META_KEY_HAS_BOUNDS);
String newHasBounds = newDesc.getMetaDataValue(OptimizerComponentConstants.META_KEY_HAS_BOUNDS);
if (oldHasBounds != null && Boolean.parseBoolean(oldHasBounds)) {
if (!Boolean.parseBoolean(newHasBounds)) {
OptimizerDynamicEndpointCommandHelper.addLowerAndUpperBoundsEndpoints(newDesc.getName(), newDesc.getDataType(),
newDesc.getMetaData(), workflowNode);
}
}
if (oldHasBounds != null && !Boolean.parseBoolean(oldHasBounds)) {
if (Boolean.parseBoolean(newHasBounds)) {
OptimizerDynamicEndpointCommandHelper.removeUpperLowerBoundsEndpoints(oldDesc.getName(), oldDesc.getMetaData(),
workflowNode);
} else {
if (!oldDesc.getName().equals(newDesc.getName())) {
OptimizerDynamicEndpointCommandHelper.removeUpperLowerBoundsEndpoints(oldDesc.getName(), oldDesc.getMetaData(),
workflowNode);
OptimizerDynamicEndpointCommandHelper.addLowerAndUpperBoundsEndpoints(newDesc.getName(), newDesc.getDataType(),
newDesc.getMetaData(), workflowNode);
}
}
}
if (refreshable != null) {
for (Refreshable r : refreshable) {
r.refresh();
}
}
}
private void handleExtraValueInputs(final WorkflowNode workflowNode, final String conditionName, final String condition2Name,
final String signature, boolean negateCondition, EndpointDescription fromDescription, EndpointDescription toDescription) {
String newConditionValueString = toDescription.getMetaDataValue(conditionName);
boolean newConditionValue = newConditionValueString != null && Boolean.parseBoolean(newConditionValueString);
String oldConditionValueString = fromDescription.getMetaDataValue(conditionName);
boolean oldConditionValue = oldConditionValueString != null && Boolean.parseBoolean(oldConditionValueString);
boolean condition2Active = false;
boolean newCondition2Value = false;
boolean oldCondition2Value = false;
if (condition2Name != null) {
condition2Active = true;
String newCondition2ValueString = toDescription.getMetaDataValue(condition2Name);
newCondition2Value = newCondition2ValueString != null && !Boolean.parseBoolean(newCondition2ValueString);
String oldCondition2ValueString = fromDescription.getMetaDataValue(condition2Name);
oldCondition2Value = oldCondition2ValueString != null && !Boolean.parseBoolean(oldCondition2ValueString);
}
boolean nameChanged = !fromDescription.getName().equals(toDescription.getName());
boolean dataTypeChanged = !fromDescription.getDataType().equals(toDescription.getDataType());
if (negateCondition) {
newConditionValue = !newConditionValue;
oldConditionValue = !oldConditionValue;
}
if ((nameChanged || dataTypeChanged) && oldConditionValue && (!condition2Active || (oldCondition2Value))) {
workflowNode.getInputDescriptionsManager().editDynamicEndpointDescription(fromDescription.getName() + signature,
toDescription.getName() + signature, toDescription.getDataType(), fromDescription.getMetaData());
}
if (oldConditionValue && newConditionValue && condition2Active) {
if (oldCondition2Value && !newCondition2Value) {
if (workflowNode.getInputDescriptionsManager().getEndpointDescription(toDescription.getName() + signature) != null) {
workflowNode.getInputDescriptionsManager().removeDynamicEndpointDescription(
toDescription.getName() + signature);
}
}
if (!oldCondition2Value && newCondition2Value) {
Map<String, String> metaData = new HashMap<>();
metaData.put(ComponentConstants.INPUT_METADATA_KEY_INPUT_EXECUTION_CONSTRAINT,
EndpointDefinition.InputExecutionContraint.Required.name());
workflowNode.getInputDescriptionsManager().addDynamicEndpointDescription(OptimizerComponentConstants.ID_STARTVALUES,
toDescription.getName() + signature, toDescription.getDataType(), metaData);
}
}
if (oldConditionValue && !newConditionValue
&& (!condition2Active || (oldCondition2Value && !newCondition2Value))) {
if (workflowNode.getInputDescriptionsManager().getEndpointDescription(toDescription.getName() + signature) != null) {
workflowNode.getInputDescriptionsManager().removeDynamicEndpointDescription(
toDescription.getName() + signature);
}
}
if (!oldConditionValue && newConditionValue) {
if (!condition2Active || (!oldCondition2Value && newCondition2Value)) {
Map<String, String> metaData = new HashMap<>();
metaData.put(ComponentConstants.INPUT_METADATA_KEY_INPUT_EXECUTION_CONSTRAINT,
EndpointDefinition.InputExecutionContraint.Required.name());
workflowNode.getInputDescriptionsManager().addDynamicEndpointDescription(OptimizerComponentConstants.ID_STARTVALUES,
toDescription.getName() + signature, toDescription.getDataType(), metaData);
}
}
}
private void executeBothHaveGradients(final WorkflowNode workflowNode) {
if (!oldDesc.getName().equals(newDesc.getName()) || oldDesc.getDataType() != newDesc.getDataType()) {
for (EndpointDescription variable : workflowNode.getOutputDescriptionsManager().getDynamicEndpointDescriptions()) {
if (!variable.getName().contains(OptimizerComponentConstants.OPTIMUM_VARIABLE_SUFFIX)) {
String oldGradientName =
OptimizerDynamicEndpointCommandHelper.createGradientChannelName(oldDesc.getName(), variable.getName());
String newGradientName =
OptimizerDynamicEndpointCommandHelper.createGradientChannelName(newDesc.getName(), variable.getName());
EndpointDescription newDesc =
workflowNode.getInputDescriptionsManager().getEndpointDescription(oldGradientName);
newDesc.setName(newGradientName);
newDesc.setDataType(this.newDesc.getDataType());
Map<String, String> gradientMetadata = new HashMap<>();
for (String key : this.newDesc.getMetaData().keySet()) {
if (key.equals(OptimizerComponentConstants.METADATA_VECTOR_SIZE)
|| key.startsWith(ComponentConstants.INPUT_METADATA_KEY_INPUT_DATUM_HANDLING)
|| key.startsWith(ComponentConstants.INPUT_METADATA_KEY_INPUT_EXECUTION_CONSTRAINT)) {
gradientMetadata.put(key, this.newDesc.getMetaData().get(key));
} else {
gradientMetadata.put(key, DASH);
}
}
newDesc.setMetaData(gradientMetadata);
workflowNode.getInputDescriptionsManager().editDynamicEndpointDescription(oldGradientName, newGradientName,
newDesc.getDataType(), newDesc.getMetaData());
}
}
}
}
private boolean hasGradient(EndpointDescription description) {
if (description.getMetaDataValue(OptimizerComponentConstants.HAS_GRADIENT) != null
&& Boolean.parseBoolean(description.getMetaDataValue(OptimizerComponentConstants.HAS_GRADIENT))) {
return true;
}
return false;
}
@Override
public void undo() {
final WorkflowNode workflowNode = getWorkflowNode();
super.undo();
switch (direction) {
case INPUT:
if (hasGradient(newDesc)) {
if (hasGradient(oldDesc)) {
undoBothHaveGradients(workflowNode);
} else {
for (EndpointDescription variable : workflowNode.getOutputDescriptionsManager().getDynamicEndpointDescriptions()) {
if (variable.getDynamicEndpointIdentifier().equals(DESIGN_VARIABLE)) {
String newGradientName =
OptimizerDynamicEndpointCommandHelper.createGradientChannelName(newDesc.getName(), variable.getName());
workflowNode.getInputDescriptionsManager().removeDynamicEndpointDescription(newGradientName);
}
}
}
} else {
if (hasGradient(oldDesc)) {
for (EndpointDescription variable : workflowNode.getOutputDescriptionsManager().getDynamicEndpointDescriptions()) {
if (variable.getDynamicEndpointIdentifier().equals(DESIGN_VARIABLE)) {
String oldGradientName =
OptimizerDynamicEndpointCommandHelper.createGradientChannelName(oldDesc.getName(), variable.getName());
Map<String, String> metaData = new HashMap<>();
for (String key : newDesc.getMetaData().keySet()) {
if (key.equals(OptimizerComponentConstants.METADATA_VECTOR_SIZE)
|| key.startsWith(ComponentConstants.INPUT_METADATA_KEY_INPUT_DATUM_HANDLING)
|| key.startsWith(ComponentConstants.INPUT_METADATA_KEY_INPUT_EXECUTION_CONSTRAINT)) {
metaData.put(key, newDesc.getMetaData().get(key));
} else {
metaData.put(key, DASH);
}
}
workflowNode.getInputDescriptionsManager().addDynamicEndpointDescription(
OptimizerComponentConstants.ID_GRADIENTS, oldGradientName,
oldDesc.getDataType(), metaData);
}
}
}
}
break;
case OUTPUT:
if (!newDesc.getName().equals(oldDesc.getName())) {
for (EndpointDescription function : workflowNode.getInputDescriptionsManager().getDynamicEndpointDescriptions()) {
if (!workflowNode.getInputDescriptionsManager().isValidEndpointName(
OptimizerDynamicEndpointCommandHelper.createGradientChannelName(function.getName(), newDesc.getName()))) {
String oldName =
OptimizerDynamicEndpointCommandHelper.createGradientChannelName(function.getName(), oldDesc.getName());
String newName =
OptimizerDynamicEndpointCommandHelper.createGradientChannelName(function.getName(), newDesc.getName());
EndpointDescription desc = workflowNode.getInputDescriptionsManager().getEndpointDescription(
OptimizerDynamicEndpointCommandHelper.createGradientChannelName(function.getName(), newDesc.getName()));
desc.setName(oldName);
workflowNode.getInputDescriptionsManager().editDynamicEndpointDescription(newName, oldName, desc.getDataType(),
desc.getMetaData());
}
}
if (getWorkflowNode().getOutputDescriptionsManager().getEndpointDescription(
newDesc.getName() + OptimizerComponentConstants.OPTIMUM_VARIABLE_SUFFIX) != null) {
getWorkflowNode().getOutputDescriptionsManager().removeDynamicEndpointDescription(
newDesc.getName() + OptimizerComponentConstants.OPTIMUM_VARIABLE_SUFFIX);
}
Map<String, String> metadata = oldDesc.getMetaData();
getWorkflowNode().getOutputDescriptionsManager().addDynamicEndpointDescription(OptimizerComponentConstants.ID_OPTIMA,
oldDesc.getName() + OptimizerComponentConstants.OPTIMUM_VARIABLE_SUFFIX,
newDesc.getDataType(), metadata);
}
handleExtraValueInputs(workflowNode, OptimizerComponentConstants.META_HAS_STARTVALUE,
null, OptimizerComponentConstants.STARTVALUE_SIGNATURE, true, newDesc, oldDesc);
handleExtraValueInputs(workflowNode, OptimizerComponentConstants.META_USE_STEP,
OptimizerComponentConstants.META_USE_UNIFIED_STEP, OptimizerComponentConstants.STEP_VALUE_SIGNATURE, false, newDesc,
oldDesc);
break;
default:
throw new RuntimeException();
}
String oldHasBounds = oldDesc.getMetaDataValue(OptimizerComponentConstants.META_KEY_HAS_BOUNDS);
String newHasBounds = newDesc.getMetaDataValue(OptimizerComponentConstants.META_KEY_HAS_BOUNDS);
if (Boolean.parseBoolean(newHasBounds)) {
if (oldHasBounds != null && !Boolean.parseBoolean(oldHasBounds)) {
OptimizerDynamicEndpointCommandHelper.addLowerAndUpperBoundsEndpoints(oldDesc.getName(), oldDesc.getDataType(),
oldDesc.getMetaData(), workflowNode);
}
} else {
if (oldHasBounds != null && !Boolean.parseBoolean(oldHasBounds)) {
if (!oldDesc.getName().equals(newDesc.getName())) {
OptimizerDynamicEndpointCommandHelper.removeUpperLowerBoundsEndpoints(newDesc.getName(), newDesc.getMetaData(),
workflowNode);
OptimizerDynamicEndpointCommandHelper.addLowerAndUpperBoundsEndpoints(oldDesc.getName(), oldDesc.getDataType(),
oldDesc.getMetaData(), workflowNode);
}
} else {
OptimizerDynamicEndpointCommandHelper.removeUpperLowerBoundsEndpoints(newDesc.getName(), newDesc.getMetaData(),
workflowNode);
}
}
if (refreshable != null) {
for (Refreshable r : refreshable) {
r.refresh();
}
}
}
private void undoBothHaveGradients(final WorkflowNode workflowNode) {
if (!oldDesc.getName().equals(newDesc.getName()) || oldDesc.getDataType() != newDesc.getDataType()) {
for (EndpointDescription variable : workflowNode.getOutputDescriptionsManager().getDynamicEndpointDescriptions()) {
if (variable.getDynamicEndpointIdentifier().equals(DESIGN_VARIABLE)) {
String oldGradientName =
OptimizerDynamicEndpointCommandHelper.createGradientChannelName(oldDesc.getName(), variable.getName());
String newGradientName =
OptimizerDynamicEndpointCommandHelper.createGradientChannelName(newDesc.getName(), variable.getName());
EndpointDescription desc =
workflowNode.getInputDescriptionsManager().getEndpointDescription(newGradientName);
desc.setName(oldGradientName);
Map<String, String> gradientMetadata = new HashMap<>();
for (String key : this.oldDesc.getMetaData().keySet()) {
if (key.equals(OptimizerComponentConstants.METADATA_VECTOR_SIZE)
|| key.startsWith(ComponentConstants.INPUT_METADATA_KEY_INPUT_DATUM_HANDLING)
|| key.startsWith(ComponentConstants.INPUT_METADATA_KEY_INPUT_EXECUTION_CONSTRAINT)) {
gradientMetadata.put(key, newDesc.getMetaData().get(key));
} else {
gradientMetadata.put(key, DASH);
}
}
desc.setMetaData(gradientMetadata);
workflowNode.getInputDescriptionsManager().editDynamicEndpointDescription(newGradientName, oldGradientName,
oldDesc.getDataType(), gradientMetadata);
}
}
}
}
}