/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.core.component.model.endpoint.api; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.node.ObjectNode; import de.rcenvironment.core.component.api.ComponentConstants; import de.rcenvironment.core.component.model.endpoint.api.EndpointDefinition.InputExecutionContraint; import de.rcenvironment.core.datamodel.api.DataType; import de.rcenvironment.core.datamodel.api.EndpointType; import de.rcenvironment.core.datamodel.api.TypedDatumConverter; import de.rcenvironment.core.datamodel.api.TypedDatumService; import de.rcenvironment.core.utils.common.JsonUtils; import de.rcenvironment.core.utils.common.StringUtils; /** * Provides information about a single endpoint. * * @author Doreen Seider */ public class EndpointDescription extends EndpointGroupDescription { private static final long serialVersionUID = -3853446362359127472L; private static TypedDatumConverter typedDatumConverter; private EndpointDefinition endpointDefinition; private DataType dataType; private Map<String, String> metaData; private Map<DataType, Integer> connectedDataTypes; private String identifier; @Deprecated public EndpointDescription() {} public EndpointDescription(EndpointDefinition newEndpointDefinition, String identifier) { super(newEndpointDefinition); this.endpointDefinition = newEndpointDefinition; this.identifier = identifier; metaData = new HashMap<String, String>(); if (endpointDefinition != null) { dataType = endpointDefinition.getDefaultDataType(); EndpointMetaDataDefinition metaDataDesc = endpointDefinition.getMetaDataDefinition(); for (String key : metaDataDesc.getMetaDataKeys()) { if (metaDataDesc.getDefaultValue(key) != null) { metaData.put(key, metaDataDesc.getDefaultValue(key)); } } } connectedDataTypes = new HashMap<DataType, Integer>(); } public EndpointDescription(EndpointDefinition newEndpointDefinition, EndpointType endpointType) { this(newEndpointDefinition, UUID.randomUUID().toString()); } /** * @return backing {@link EndpointDefinition} */ public EndpointDefinition getEndpointDefinition() { return endpointDefinition; } public DataType getDataType() { return dataType; } /** * @param type data type to set. */ public void setDataType(DataType type) { if (endpointDefinition != null && !endpointDefinition.getPossibleDataTypes().contains(type)) { throw new IllegalArgumentException(StringUtils.format("Given data type '%s' for endpoint '%s' is invalid", type, getName())); } this.dataType = type; } /** * @param type {@link DataType} to check * @return <code>true</code> if is is valid (is possible data type and all connected outputs are compatible), otherwise * <code>false</code> */ public boolean isDataTypeValid(DataType type) { if (endpointDefinition == null || !endpointDefinition.getPossibleDataTypes().contains(type)) { return false; } for (DataType t : connectedDataTypes.keySet()) { if (endpointDefinition.getEndpointType() == EndpointType.INPUT) { if (t != type && !typedDatumConverter.isConvertibleTo(t, type)) { return false; } } else { if (t != type && !typedDatumConverter.isConvertibleTo(type, t)) { return false; } } } return true; } /** * @param key key of meta data to get * @return meta data value for this key or <code>null</code> if there is no one defined for this key */ public String getMetaDataValue(String key) { return metaData.get(key); } /** * @param configuration current configuration used to get active meta data * @return currently active meta data */ public Map<String, String> getActiveMetaData(Map<String, String> configuration) { Map<String, String> activeMetaData = new HashMap<>(); for (String metaDataKey : metaData.keySet()) { Map<String, List<String>> activationFilter = endpointDefinition .getMetaDataDefinition().getActivationFilter(metaDataKey); for (String configKey : activationFilter.keySet()) { if (configuration.containsKey(configKey) && activationFilter.get(configKey).contains(configuration.get(configKey))) { activeMetaData.put(metaDataKey, metaData.get(metaDataKey)); } } } return activeMetaData; } /** * @return currently active meta data */ public Map<String, String> getMetaDataToPersist() { Map<String, String> persistentMetaData = new HashMap<>(); ObjectMapper mapper = JsonUtils.getDefaultObjectMapper(); for (String metaDataKey : metaData.keySet()) { if (endpointDefinition.getMetaDataDefinition().isPersistent(metaDataKey)) { ObjectNode rootNode = mapper.createObjectNode(); rootNode.put("guiName", endpointDefinition.getMetaDataDefinition().getGuiName(metaDataKey)); rootNode.put("value", getMetaDataValue(metaDataKey)); persistentMetaData.put(metaDataKey, rootNode.toString()); } } return persistentMetaData; } public Map<String, String> getMetaData() { return metaData; } /** * @param key key of meta data to set * @param value meta data value to set */ public void setMetaDataValue(String key, String value) { metaData.put(key, value); } /** * @param newMetaData meta data to set */ public void setMetaData(Map<String, String> newMetaData) { metaData = newMetaData; } /** * @param type data type this endpoint is connected to */ public void addConnectedDataType(DataType type) { if (connectedDataTypes.containsKey(type) && connectedDataTypes.get(type) != 0) { connectedDataTypes.put(type, connectedDataTypes.get(type) + 1); } else { connectedDataTypes.put(type, 1); } } /** * @param type data type this endpoint is not connected to anymore */ public void removeConnectedDataType(DataType type) { if (connectedDataTypes.containsKey(type)) { connectedDataTypes.put(type, connectedDataTypes.get(type) - 1); if (connectedDataTypes.get(type) <= 0) { connectedDataTypes.remove(type); } } } public List<DataType> getConnectedDataTypes() { return new ArrayList<DataType>(connectedDataTypes.keySet()); } public boolean isConnected() { return !connectedDataTypes.isEmpty(); } /** * @return <code>true</code> if the input execution constraint is {@link InputExecutionContraint#Required} */ public boolean isRequired() { // endpointDefinition is null if the component doesn't exist, then only an EndpointDescription instance exists in order to show the // endpoint in the GUI, but it is kind of empty so to say (without the actual definition behind) if (endpointDefinition == null || endpointDefinition.getEndpointType().equals(EndpointType.OUTPUT)) { return false; } EndpointDefinition.InputExecutionContraint exeConstraint = getEndpointDefinition().getDefaultInputExecutionConstraint(); if (getMetaDataValue(ComponentConstants.INPUT_METADATA_KEY_INPUT_EXECUTION_CONSTRAINT) != null) { exeConstraint = EndpointDefinition.InputExecutionContraint.valueOf( getMetaDataValue(ComponentConstants.INPUT_METADATA_KEY_INPUT_EXECUTION_CONSTRAINT)); } return exeConstraint.equals(EndpointDefinition.InputExecutionContraint.Required); } /** * Copies the {@link EndpointDescription} instance. * * @param endpointDescription {@link EndpointDescription} to copy * @return {@link EndpointDescription} copied */ public static EndpointDescription copy(EndpointDescription endpointDescription) { EndpointDescription copiedDesc = new EndpointDescription(endpointDescription.getEndpointDefinition(), endpointDescription.getIdentifier()); copiedDesc.setDataType(endpointDescription.getDataType()); copiedDesc.setDynamicEndpointIdentifier(endpointDescription.getDynamicEndpointIdentifier()); copiedDesc.setParentGroupName(endpointDescription.getParentGroupName()); for (DataType type : endpointDescription.getConnectedDataTypes()) { copiedDesc.addConnectedDataType(type); } for (String key : endpointDescription.getMetaData().keySet()) { if (endpointDescription.getMetaData().get(key) != null) { copiedDesc.setMetaDataValue(key, endpointDescription.getMetaData().get(key)); } } try { copiedDesc.setName(endpointDescription.getName()); } catch (UnsupportedOperationException e) { // nothing to do here. it says that we have an static endpoint here. name is // unmodifiable and already defined in declarative description e = null; } return copiedDesc; } public String getIdentifier() { return identifier; } public void setIdentifier(String newIdentifier) { identifier = newIdentifier; } protected void bindTypedDatumService(TypedDatumService typedDatumService) { typedDatumConverter = typedDatumService.getConverter(); } }