/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.core.gui.workflow.execute; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; import org.apache.commons.logging.LogFactory; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.ColumnViewer; import org.eclipse.jface.viewers.ComboBoxCellEditor; import org.eclipse.jface.viewers.EditingSupport; import org.eclipse.jface.viewers.TableViewer; import de.rcenvironment.core.communication.common.InstanceNodeSessionId; import de.rcenvironment.core.communication.common.LogicalNodeId; import de.rcenvironment.core.component.api.ComponentUtils; import de.rcenvironment.core.component.api.DistributedComponentKnowledge; import de.rcenvironment.core.component.api.DistributedComponentKnowledgeService; import de.rcenvironment.core.component.model.api.ComponentDescription; import de.rcenvironment.core.component.model.api.ComponentInstallation; import de.rcenvironment.core.component.workflow.model.api.WorkflowNode; import de.rcenvironment.core.utils.incubator.ServiceRegistry; import de.rcenvironment.core.utils.incubator.ServiceRegistryAccess; /** * ComboBox editing for selecting target platform for each component. * * @author Heinrich Wendel * @author Christian Weiss */ final class TargetNodeEditingSupport extends EditingSupport { private static final int ERROR = -1; private final NodeIdentifierConfigurationHelper nodeIdConfigHelper; private final int column; private final ColumnViewer viewer; private final LogicalNodeId localNode; private Map<String, List<String>> values = new HashMap<String, List<String>>(); /** Backing {@link InstanceNodeSessionId}s sorted as the are displayed in the combo box. */ private Map<String, List<LogicalNodeId>> nodes = new HashMap<String, List<LogicalNodeId>>(); private DistributedComponentKnowledge compKnowledge; private final ServiceRegistryAccess serviceRegistryAccess; private Map<String, Map<LogicalNodeId, Integer>> matchingNodeInfo = new HashMap<String, Map<LogicalNodeId, Integer>>(); private Map<WorkflowNode, Boolean> hasVersionErrorMap = new HashMap<WorkflowNode, Boolean>(); private Map<WorkflowNode, ComponentDescription> initialComponentDescriptions = new HashMap<WorkflowNode, ComponentDescription>(); TargetNodeEditingSupport(final NodeIdentifierConfigurationHelper nodeIdConfigHelper, final LogicalNodeId localNode, final ColumnViewer viewer, final int column) { super(viewer); this.nodeIdConfigHelper = nodeIdConfigHelper; this.column = column; this.viewer = viewer; this.localNode = localNode; serviceRegistryAccess = ServiceRegistry.createAccessFor(this); compKnowledge = serviceRegistryAccess.getService(DistributedComponentKnowledgeService.class).getCurrentComponentKnowledge(); } @Override protected boolean canEdit(Object arg0) { return column == 1; } @Override protected CellEditor getCellEditor(Object element) { if (!(element instanceof WorkflowNode)) { return null; } ComboBoxCellEditor editor = new ComboBoxCellEditor(((TableViewer) viewer).getTable(), getValues((WorkflowNode) element) .toArray(new String[] {})); return editor; } protected boolean isNodeExactMatchRegardingComponentVersion(WorkflowNode node) { return isNodeExactMatchRegardingComponentVersion(node, node.getComponentDescription().getNode()); } protected boolean isNodeExactMatchRegardingInitialComponentVersion(WorkflowNode node) { return isNodeExactMatchRegardingComponentVersion(node, initialComponentDescriptions.get(node).getNode()); } protected boolean isNodeExactMatchRegardingComponentVersion(WorkflowNode wfNode, LogicalNodeId node) { if (node == null) { node = localNode; } return matchingNodeInfo.get(wfNode.getIdentifier()).containsKey(node) && matchingNodeInfo.get(wfNode.getIdentifier()).get(node).equals(ComponentUtils.EQUAL_COMPONENT_VERSION); } /** * {@inheritDoc}. * <p> * The returned value is preferably the one specified in the {@link ComponentDescription}, but if this platform is not able to execute * this type of node, another valid platform is chosen (which would be indicated by a return value of 'true' through * {@link #isValueSuggestion(WorkflowNode)}). * </p> * * @see org.eclipse.jface.viewers.EditingSupport#getValue(java.lang.Object) */ @Override protected Object getValue(Object element) { Integer result = null; if (!(element instanceof WorkflowNode) || column != 1) { return result; } LogicalNodeId node = ((WorkflowNode) element).getComponentDescription().getNode(); if (isNodeExactMatchRegardingComponentVersion((WorkflowNode) element)) { if (node.equals(localNode)) { result = 0; } else { result = nodes.get(((WorkflowNode) element).getIdentifier()).indexOf(node); } } else { for (LogicalNodeId p : nodes.get(((WorkflowNode) element).getIdentifier())) { // if (isNodeExactMatchRegardingComponentVersion((WorkflowNode) element, p)) { // result = nodes.get(((WorkflowNode) element).getIdentifier()).indexOf(p); if (node.equals(p)) { result = nodes.get(((WorkflowNode) element).getIdentifier()).indexOf(p); } break; } } if (result == null && !nodes.isEmpty()) { result = 0; } return result; } @Override protected void setValue(Object element, Object value) { int intValue = ((Integer) value).intValue(); if (intValue >= 0) { ComponentInstallation installation; if (nodes.get(((WorkflowNode) element).getIdentifier()).get(intValue) == null || nodes.get(((WorkflowNode) element).getIdentifier()).get(intValue).equals(localNode)) { installation = ComponentUtils.getComponentInstallationForNode( ((WorkflowNode) element).getComponentDescription().getIdentifier(), compKnowledge.getLocalInstallations(), localNode); } else { installation = ComponentUtils.getComponentInstallationForNode( ((WorkflowNode) element).getComponentDescription().getIdentifier(), compKnowledge.getPublishedInstallationsOnNode( nodes.get(((WorkflowNode) element).getIdentifier()).get(intValue)), nodes.get(((WorkflowNode) element).getIdentifier()).get(intValue)); } if (installation != null) { ((WorkflowNode) element).getComponentDescription().setComponentInstallationAndUpdateConfiguration(installation); } } } /** * Sets a remote instance (random in list) for the WorkflowNode. */ public int setRemoteValue(WorkflowNode node) { ComponentInstallation installation = null; int comboindex = ERROR; List<LogicalNodeId> nodeIdentifierList = nodes.get(node.getIdentifier()); List<Integer> remoteIndexList = new ArrayList<Integer>(); for (int i = 0; i < nodeIdentifierList.size(); i++) { if (nodes.get(node.getIdentifier()).get(i) != null) { if (!(nodes.get(node.getIdentifier()).get(i).equals(localNode))) { if (isNodeExactMatchRegardingComponentVersion(node, nodes .get(node.getIdentifier()).get(i)) && isNodeExactMatchRegardingInitialComponentVersion(node)) { remoteIndexList.add(i); } } } } if (!remoteIndexList.isEmpty()) { Random random = new Random(); int randomIndex = remoteIndexList.get(random.nextInt(remoteIndexList.size())); installation = ComponentUtils.getComponentInstallationForNode( node.getComponentDescription().getIdentifier(), compKnowledge.getPublishedInstallationsOnNode( nodes.get(node.getIdentifier()).get(randomIndex)), nodes.get(node.getIdentifier()).get(randomIndex)); comboindex = randomIndex; setValue(node, randomIndex); } if (installation != null) { node.getComponentDescription().setComponentInstallationAndUpdateConfiguration(installation); } return comboindex; } /** * Builds and returns the list of available platforms for the given {@link WorkflowNode}. * * @param wfNode The {@link WorkflowNode}. * @return The list of strings representing the available platforms for the given {@link WorkflowNode}. */ protected List<String> getValues(WorkflowNode wfNode) { compKnowledge = serviceRegistryAccess.getService(DistributedComponentKnowledgeService.class).getCurrentComponentKnowledge(); if (!wfNode.isInit()) { initialComponentDescriptions.put(wfNode, wfNode.getComponentDescription().clone()); wfNode.setInit(true); } boolean hasVersionError = false; if (hasVersionErrorMap.containsKey(wfNode)) { if (hasVersionErrorMap.get(wfNode).equals(true)) { // return values.get(wfNode.getIdentifier()); hasVersionError = true; } } synchronized (nodes) { if (!nodes.containsKey((wfNode.getIdentifier()))) { nodes.put(wfNode.getIdentifier(), new ArrayList<LogicalNodeId>()); } nodes.get(wfNode.getIdentifier()).clear(); } // Nodes don't get refreshed at the moment when the selected node has a version error. if (!hasVersionError) { matchingNodeInfo.put(wfNode.getIdentifier(), nodeIdConfigHelper.getTargetPlatformsForComponent(wfNode.getComponentDescription())); } else { matchingNodeInfo.put(wfNode.getIdentifier(), nodeIdConfigHelper.getTargetPlatformsForComponent(initialComponentDescriptions.get(wfNode))); } List<LogicalNodeId> sortedTargetNodes = new ArrayList<LogicalNodeId>(matchingNodeInfo.get(wfNode.getIdentifier()).keySet()); nodeIdConfigHelper.sortNodes(sortedTargetNodes); List<String> nodeValues = new ArrayList<String>(nodes.size()); // add the *local* option as the topmost one, if the local node supports the component if (sortedTargetNodes.contains(localNode)) { nodeValues.add(enhanceNodeNameWithVersionInformation(wfNode, localNode.getAssociatedDisplayName() + " " + Messages.localPlatformSelectionTitle, localNode)); nodes.get(wfNode.getIdentifier()).add(null); } // add all supporting nodes to the list of choices for (LogicalNodeId n : sortedTargetNodes) { if (n == null) { LogFactory.getLog(getClass()).error("NULL NodeIdentifier!"); continue; } String nodeName = n.getAssociatedDisplayName(); if (!n.equals(localNode)) { nodeValues.add(enhanceNodeNameWithVersionInformation(wfNode, nodeName, n)); nodes.get(wfNode.getIdentifier()).add(n); } } values.put(wfNode.getIdentifier(), nodeValues); return nodeValues; } private String enhanceNodeNameWithVersionInformation(WorkflowNode wfNode, String nodeName, LogicalNodeId node) { if (matchingNodeInfo.get(wfNode.getIdentifier()).get(node).equals(ComponentUtils.LOWER_COMPONENT_VERSION)) { nodeName = nodeName + " " + Messages.older; } else if (matchingNodeInfo.get(wfNode.getIdentifier()).get(node).equals(ComponentUtils.GREATER_COMPONENT_VERSION)) { nodeName = nodeName + " " + Messages.newer; } return nodeName; } public Map<WorkflowNode, Boolean> getHasVersionErrorMap() { return hasVersionErrorMap; } }