/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.core.component.execution.impl;
import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import de.rcenvironment.core.communication.api.ServiceCallContext;
import de.rcenvironment.core.communication.api.ServiceCallContextUtils;
import de.rcenvironment.core.communication.common.LogicalNodeId;
import de.rcenvironment.core.component.api.ComponentConstants;
import de.rcenvironment.core.component.datamanagement.api.ComponentHistoryDataItem;
import de.rcenvironment.core.component.execution.api.ComponentContext;
import de.rcenvironment.core.component.execution.api.ComponentExecutionContext;
import de.rcenvironment.core.component.execution.api.ComponentLog;
import de.rcenvironment.core.component.execution.api.ConsoleRow;
import de.rcenvironment.core.component.execution.api.ConsoleRow.Type;
import de.rcenvironment.core.component.execution.api.ConsoleRow.WorkflowLifecyleEventType;
import de.rcenvironment.core.component.execution.api.PersistedComponentData;
import de.rcenvironment.core.component.execution.internal.ComponentContextBridge;
import de.rcenvironment.core.component.model.configuration.api.ConfigurationDescription;
import de.rcenvironment.core.component.model.endpoint.api.EndpointDefinition;
import de.rcenvironment.core.component.model.endpoint.api.EndpointDescription;
import de.rcenvironment.core.datamodel.api.DataType;
import de.rcenvironment.core.datamodel.api.EndpointCharacter;
import de.rcenvironment.core.datamodel.api.TypedDatum;
import de.rcenvironment.core.utils.common.StringUtils;
import de.rcenvironment.core.utils.incubator.ServiceRegistry;
import de.rcenvironment.core.utils.incubator.ServiceRegistryAccess;
/**
* Implementation of {@link ComponentContext}.
*
* @author Doreen Seider
* @author Robert Mischke
*/
public class ComponentContextImpl implements ComponentContext {
private static final long serialVersionUID = -8834897231211155860L;
private String compExeId;
private String instanceName;
private final LogicalNodeId node;
private final String wfExeCrtlId;
private final String wfCtrlInstanceName;
private final LogicalNodeId wfCtrlNode;
private LogicalNodeId defaultStorageNode;
private File workingDirectory;
private final ConfigurationDescription configurationDescription;
private final Set<String> inputs = new HashSet<>();
private final Set<String> inputsNotConnected = new HashSet<>();
private final Set<String> outputs = new HashSet<>();
private final Map<String, String> dynInputsIds = new HashMap<>();
private final Map<String, String> dynOutputsIds = new HashMap<>();
private final Map<String, DataType> outputsDataTypes = new HashMap<>();
private final Map<String, DataType> inputsDataTypes = new HashMap<>();
private final Map<String, EndpointCharacter> outputsCharacter = new HashMap<>();
private final Map<String, EndpointCharacter> inputsCharacter = new HashMap<>();
private final Map<String, Map<String, String>> inputsMetaData = new HashMap<>();
private final Map<String, Map<String, String>> outputsMetaData = new HashMap<>();
private final String componentIdentifier;
private final String componentName;
private final ComponentContextBridge compExeCtxBridge;
private final ServiceRegistryAccess serviceRegistryAccess;
private final ComponentLog log = new ComponentLog() {
@Override
public void toolStdout(String message) {
compExeCtxBridge.printConsoleRow(message, Type.TOOL_OUT);
}
@Override
public void toolStderr(String message) {
compExeCtxBridge.printConsoleRow(message, Type.TOOL_ERROR);
}
@Override
public void componentWarn(String message) {
compExeCtxBridge.printConsoleRow(message, Type.COMPONENT_WARN);
}
@Override
public void componentInfo(String message) {
compExeCtxBridge.printConsoleRow(message, Type.COMPONENT_INFO);
}
@Override
public void componentError(String message) {
compExeCtxBridge.printConsoleRow(message, Type.COMPONENT_ERROR);
}
@Override
public void componentError(String message, Throwable t, String errorId) {
compExeCtxBridge.printConsoleRow(StringUtils.format("%s: %s (%s)", message, t.getMessage(), errorId), Type.COMPONENT_ERROR);
}
};
public ComponentContextImpl(ComponentExecutionContext compExeCtx, ComponentContextBridge compExeCtxBridge) {
compExeId = compExeCtx.getExecutionIdentifier();
instanceName = compExeCtx.getInstanceName();
node = compExeCtx.getNodeId();
wfCtrlNode = compExeCtx.getWorkflowNodeId();
wfExeCrtlId = compExeCtx.getWorkflowExecutionIdentifier();
wfCtrlInstanceName = compExeCtx.getWorkflowInstanceName();
defaultStorageNode = compExeCtx.getWorkflowNodeId();
workingDirectory = compExeCtx.getWorkingDirectory();
configurationDescription = compExeCtx.getComponentDescription().getConfigurationDescription();
for (EndpointDescription ep : compExeCtx.getComponentDescription().getInputDescriptionsManager().getEndpointDescriptions()) {
String inputExecutionConstraint = ep.getMetaData().get(ComponentConstants.INPUT_METADATA_KEY_INPUT_EXECUTION_CONSTRAINT);
if (inputExecutionConstraint == null) {
inputExecutionConstraint = ep.getEndpointDefinition().getDefaultInputExecutionConstraint().name();
}
if (inputExecutionConstraint.equals(EndpointDefinition.InputExecutionContraint.Required.name()) || ep.isConnected()) {
inputs.add(ep.getName());
dynInputsIds.put(ep.getName(), ep.getDynamicEndpointIdentifier());
} else if (!ep.isConnected()) {
inputsNotConnected.add(ep.getName());
}
inputsDataTypes.put(ep.getName(), ep.getDataType());
inputsCharacter.put(ep.getName(), ep.getEndpointDefinition().getEndpointCharacter());
inputsMetaData.put(ep.getName(), ep.getMetaData());
}
for (EndpointDescription ep : compExeCtx.getComponentDescription().getOutputDescriptionsManager().getEndpointDescriptions()) {
outputs.add(ep.getName());
dynOutputsIds.put(ep.getName(), ep.getDynamicEndpointIdentifier());
outputsDataTypes.put(ep.getName(), ep.getDataType());
outputsCharacter.put(ep.getName(), ep.getEndpointDefinition().getEndpointCharacter());
outputsMetaData.put(ep.getName(), ep.getMetaData());
}
componentIdentifier = compExeCtx.getComponentDescription().getIdentifier();
componentName = compExeCtx.getComponentDescription().getName();
this.compExeCtxBridge = compExeCtxBridge;
serviceRegistryAccess = ServiceRegistry.createAccessFor(this);
}
@Override
public String getExecutionIdentifier() {
return compExeId;
}
@Override
public String getInstanceName() {
return instanceName;
}
@Override
public LogicalNodeId getNodeId() {
return node;
}
@Override
public LogicalNodeId getDefaultStorageNodeId() {
return defaultStorageNode;
}
@Override
public File getWorkingDirectory() {
return workingDirectory;
}
public void setInstanceIdentifier(String instanceIdentifier) {
this.compExeId = instanceIdentifier;
}
public void setInstanceName(String instanceName) {
this.instanceName = instanceName;
}
public void setDefaultStorageNode(LogicalNodeId defaultStorageNode) {
this.defaultStorageNode = defaultStorageNode;
}
public void setWorkingDirectory(File workingDirectory) {
this.workingDirectory = workingDirectory;
}
@Override
public Set<String> getReadOnlyConfigurationKeys() {
return Collections.unmodifiableSet(configurationDescription.getComponentConfigurationDefinition().getReadOnlyConfiguration()
.getConfigurationKeys());
}
@Override
public Set<String> getConfigurationKeys() {
return Collections.unmodifiableSet(configurationDescription.getConfiguration().keySet());
}
@Override
public String getConfigurationValue(String key) {
if (getConfigurationKeys().contains(key)) {
return configurationDescription.getConfigurationValue(key);
} else if (getReadOnlyConfigurationKeys().contains(key)) {
return configurationDescription.getComponentConfigurationDefinition().getReadOnlyConfiguration().getValue(key);
} else {
return null;
}
}
@Override
public String getConfigurationMetaDataValue(String configKey, String metaDataKey) {
return configurationDescription.getComponentConfigurationDefinition().getConfigurationMetaDataDefinition()
.getMetaDataValue(configKey, metaDataKey);
}
@Override
public Set<String> getInputs() {
return Collections.unmodifiableSet(inputs);
}
@Override
public boolean isStaticInput(String inputName) {
return getDynamicInputIdentifier(inputName) == null;
}
@Override
public boolean isDynamicInput(String inputName) {
return getDynamicInputIdentifier(inputName) != null;
}
@Override
public boolean isDynamicOutput(String outputName) {
return getDynamicOutputIdentifier(outputName) != null;
}
@Override
public Set<String> getInputsWithDatum() {
return Collections.unmodifiableSet(compExeCtxBridge.getInputsWithDatum());
}
@Override
public DataType getInputDataType(String inputName) {
return inputsDataTypes.get(inputName);
}
@Override
public Set<String> getInputMetaDataKeys(String inputName) {
return Collections.unmodifiableSet(inputsMetaData.keySet());
}
@Override
public String getInputMetaDataValue(String inputName, String metaDataKey) {
return inputsMetaData.get(inputName).get(metaDataKey);
}
@Override
public TypedDatum readInput(String inputName) {
return compExeCtxBridge.readInput(inputName);
}
@Override
public Set<String> getOutputs() {
return Collections.unmodifiableSet(outputs);
}
@Override
public DataType getOutputDataType(String outputName) {
return outputsDataTypes.get(outputName);
}
@Override
public Set<String> getOutputMetaDataKeys(String outputName) {
return Collections.unmodifiableSet(outputsMetaData.keySet());
}
@Override
public String getOutputMetaDataValue(String outputName, String metaDataKey) {
return outputsMetaData.get(outputName).get(metaDataKey);
}
@Override
public void writeOutput(String outputName, TypedDatum value) {
compExeCtxBridge.writeOutput(outputName, value);
}
@Override
public void resetOutput(String outputName) {
compExeCtxBridge.resetOutput(outputName);
}
@Override
public void closeOutput(String outputName) {
compExeCtxBridge.closeOutput(outputName);
}
@Override
public void closeAllOutputs() {
compExeCtxBridge.closeAllOutputs();
}
@Override
public boolean isOutputClosed(String outputName) {
return compExeCtxBridge.isOutputClosed(outputName);
}
@Override
public <T> T getService(Class<T> clazz) {
return serviceRegistryAccess.getService(clazz);
}
@Override
public int getExecutionCount() {
return compExeCtxBridge.getExecutionCount();
}
@Override
public LogicalNodeId getWorkflowNodeId() {
return wfCtrlNode;
}
@Override
public String getWorkflowExecutionIdentifier() {
return wfExeCrtlId;
}
@Override
public String getWorkflowInstanceName() {
return wfCtrlInstanceName;
}
@Override
public PersistedComponentData getPersistedData() {
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void writeIntermediateHistoryData(ComponentHistoryDataItem historyDataItem) {
compExeCtxBridge.writeIntermediateHistoryData(historyDataItem);
}
@Override
public void writeFinalHistoryDataItem(ComponentHistoryDataItem historyDataItem) {
compExeCtxBridge.writeFinalHistoryDataItem(historyDataItem);
}
@Override
public String getDynamicInputIdentifier(String inputName) {
return dynInputsIds.get(inputName);
}
@Override
public String getDynamicOutputIdentifier(String inputName) {
return dynOutputsIds.get(inputName);
}
@Override
public String getComponentIdentifier() {
return componentIdentifier;
}
@Override
public String getComponentName() {
return componentName;
}
public Long getComponentExecutionDataManagementId() {
return compExeCtxBridge.getComponentExecutionDataManagementId();
}
@Override
public Set<String> getInputsNotConnected() {
return inputsNotConnected;
}
@Override
public ComponentLog getLog() {
return log;
}
@Override
public ServiceCallContext getServiceCallContext() {
return ServiceCallContextUtils.getCurrentServiceCallContext();
}
@Override
public void announceExternalProgramStart() {
compExeCtxBridge.printConsoleRow(WorkflowLifecyleEventType.TOOL_STARTING.name(), ConsoleRow.Type.LIFE_CYCLE_EVENT);
}
@Override
public void announceExternalProgramTermination() {
compExeCtxBridge.printConsoleRow(WorkflowLifecyleEventType.TOOL_FINISHED.name(), ConsoleRow.Type.LIFE_CYCLE_EVENT);
}
@Override
public EndpointCharacter getInputCharacter(String inputName) {
return inputsCharacter.get(inputName);
}
@Override
public EndpointCharacter getOutputCharacter(String outputName) {
return outputsCharacter.get(outputName);
}
@Override
public List<String> getDynamicInputsWithIdentifier(String identifier) {
List<String> result = new LinkedList<>();
for (String endpoint : inputs) {
if (isDynamicInput(endpoint) && getDynamicInputIdentifier(endpoint).equals(identifier)) {
result.add(endpoint);
}
}
return result;
}
@Override
public List<String> getDynamicOutputsWithIdentifier(String identifier) {
List<String> result = new LinkedList<>();
for (String endpoint : outputs) {
if (isDynamicOutput(endpoint) && getDynamicOutputIdentifier(endpoint).equals(identifier)) {
result.add(endpoint);
}
}
return result;
}
}