| /******************************************************************************* |
| * Copyright (c) 2018 Agence spatiale canadienne / Canadian Space Agency |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Pierre Allard, |
| * Regent L'Archeveque, |
| * Sebastien Gemme - initial API and implementation |
| * |
| * SPDX-License-Identifier: EPL-1.0 |
| * |
| *******************************************************************************/ |
| package org.eclipse.apogy.common.topology.ui.impl; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.apogy.common.topology.AbstractNodeVisitor; |
| import org.eclipse.apogy.common.topology.GroupNode; |
| import org.eclipse.apogy.common.topology.Node; |
| import org.eclipse.apogy.common.topology.ui.Activator; |
| import org.eclipse.apogy.common.topology.ui.ApogyCommonTopologyUIFactory; |
| import org.eclipse.apogy.common.topology.ui.NodePresentation; |
| import org.eclipse.apogy.common.topology.ui.NodePresentationAdapter; |
| import org.eclipse.apogy.common.topology.ui.TopologyPresentationSet; |
| import org.eclipse.apogy.common.topology.ui.internal.MultiNodeListener; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| public class TopologyPresentationRegistryCustomImpl extends TopologyPresentationRegistryImpl { |
| |
| private static final Logger Logger = LoggerFactory.getLogger(TopologyPresentationRegistryImpl.class); |
| |
| private MultiNodeListener multiNodeListener = null; |
| private final Map<Node, NodePresentation> nodeToNodePresentationMap = new HashMap<Node, NodePresentation>(100); |
| |
| @Override |
| public TopologyPresentationSet createTopologyPresentationSet(Node topologyRoot) { |
| final TopologyPresentationSet topologyPresentationSet = ApogyCommonTopologyUIFactory.eINSTANCE |
| .createTopologyPresentationSet(); |
| |
| // Visit the topology spanned by the topologyRoot. |
| AbstractNodeVisitor visitor = new AbstractNodeVisitor() { |
| @Override |
| public void visit(Node node) { |
| // Check to see if the registry already contains a NodePresentation associated |
| // with node. |
| NodePresentation nodePresentation = getPresentationNode(node); |
| |
| // If no NodePresentation has been found, attempts to create one. |
| if (nodePresentation == null) { |
| nodePresentation = createNodePresentation(node); |
| |
| // If a NodePresentation was successfully created, add it to the list |
| if (nodePresentation != null) { |
| addNodePresentation(nodePresentation); |
| } |
| } |
| |
| // If a NodePresentation was found or created. |
| if (nodePresentation != null) { |
| // Adds the NodePresenation to the TopologyPresentationSet. |
| topologyPresentationSet.getNodePresentationList().add(nodePresentation); |
| |
| // Adds the TopologyPresentationSet to the nodePresentation. |
| nodePresentation.getTopologyPresentationSet().add(topologyPresentationSet); |
| } |
| } |
| }; |
| topologyRoot.accept(visitor); |
| |
| getTopologyPresentationSetList().add(topologyPresentationSet); |
| |
| return topologyPresentationSet; |
| } |
| |
| public void release(final TopologyPresentationSet topologyPresentationSet) { |
| if (topologyPresentationSet != null) { |
| for (Node node : topologyPresentationSet.getNodes()) { |
| NodePresentation nodePresentation = getPresentationNode(node); |
| |
| if (nodePresentation != null) { |
| nodePresentation.getTopologyPresentationSet().remove(topologyPresentationSet); |
| |
| // If the NodePresentation is no longer in use, release it. |
| if (nodePresentation.getTopologyPresentationSet().isEmpty()) { |
| // Remove the nodePresentation |
| removeNodePresentation(nodePresentation); |
| } |
| } |
| } |
| |
| // Have the TopologyPresentationSet release all references to Node, Node |
| // Presentation and TopologyPresentationRegistry. |
| topologyPresentationSet.getNodePresentationList().clear(); |
| topologyPresentationSet.setTopologyPresentationRegistry(null); |
| } |
| } |
| |
| @Override |
| public NodePresentation getPresentationNode(Node node) { |
| return this.nodeToNodePresentationMap.get(node); |
| } |
| |
| private NodePresentation createNodePresentation(Node node) { |
| Logger.debug("TopologyPresentationRegistryImpl.createNodePresentation(" + node + ")"); |
| |
| NodePresentation nodePresentation = null; |
| |
| // Gets the NodePresentation Adapter associated with the topology node. |
| NodePresentationAdapter adapter = Activator.getDefault().getNodePresentationAdapterFactory() |
| .getAdapterFor(node); |
| if (adapter != null) { |
| // Attempts to create the NodePresentation associated with the node. |
| nodePresentation = adapter.getAdapter(node, null); |
| } |
| |
| return nodePresentation; |
| } |
| |
| private synchronized void addNodePresentation(NodePresentation nodePresentation) { |
| // Adds the NodePresentation to the list of NodePresentation. |
| getNodePresentationList().add(nodePresentation); |
| |
| // Adds the Node and its NodePresentation to the map. |
| this.nodeToNodePresentationMap.put(nodePresentation.getNode(), nodePresentation); |
| |
| // Registers a listener to the underlying Node. |
| getMultiNodeListener().registerNode(nodePresentation.getNode()); |
| |
| // Update the affected TopologyPresentationSet |
| if (nodePresentation.getNode().getParent() instanceof GroupNode) { |
| // Here we need to check the parent node to figure out who is affected. |
| GroupNode parent = (GroupNode) nodePresentation.getNode().getParent(); |
| List<TopologyPresentationSet> affectedTopologyPresentationSet = getAffectedTopologyPresentationSet(parent); |
| |
| // Update each TopologyPresentationSet affected. |
| for (TopologyPresentationSet topologyPresentationSet : affectedTopologyPresentationSet) { |
| try { |
| topologyPresentationSet.getNodePresentationList().add(nodePresentation); |
| } catch (Throwable t) { |
| Logger.error(t.getMessage(), t); |
| } |
| } |
| } |
| } |
| |
| private synchronized void removeNodePresentation(NodePresentation nodePresentation) { |
| // Un-Registers a listener from the underlying Node. |
| getMultiNodeListener().unregisterNode(nodePresentation.getNode()); |
| |
| // Here we need to check the node itself to figure out who is affected. |
| List<TopologyPresentationSet> affectedTopologyPresentationSet = new ArrayList<TopologyPresentationSet>( |
| nodePresentation.getTopologyPresentationSet()); |
| |
| // Update each TopologyPresentationSet affected. |
| for (TopologyPresentationSet topologyPresentationSet : affectedTopologyPresentationSet) { |
| try { |
| topologyPresentationSet.getNodePresentationList().remove(nodePresentation); |
| } catch (Throwable t) { |
| Logger.error(t.getMessage(), t); |
| } |
| } |
| |
| // Removes the Node and its NodePresentation from the map. |
| this.nodeToNodePresentationMap.remove(nodePresentation.getNode()); |
| |
| // Removes the NodePresentation from the list. |
| getNodePresentationList().remove(nodePresentation); |
| } |
| |
| private synchronized void addNodeAndChildrens(Node topologyRoot) { |
| Logger.debug("TopologyPresentationRegistryImpl.addNodeAndChildrens(" + topologyRoot + ")"); |
| |
| // Visit the topology spanned by the topologyRoot. |
| AbstractNodeVisitor visitor = new AbstractNodeVisitor() { |
| @Override |
| public void visit(Node node) { |
| Logger.debug("/t CHILD " + node); |
| |
| NodePresentation nodePresentation = getPresentationNode(node); |
| |
| // NodePresentation not created yet, create one. |
| if (nodePresentation == null) { |
| nodePresentation = createNodePresentation(node); |
| if (nodePresentation != null) { |
| addNodePresentation(nodePresentation); |
| } else { |
| Logger.warn("No NodePresentation found for node <" + node + ">."); |
| } |
| } |
| } |
| }; |
| topologyRoot.accept(visitor); |
| } |
| |
| private synchronized void removeNodeAndChildrens(Node topologyRoot) { |
| // Visit the topology spanned by the topologyRoot. |
| AbstractNodeVisitor visitor = new AbstractNodeVisitor() { |
| @Override |
| public void visit(Node node) { |
| NodePresentation nodePresentation = getPresentationNode(node); |
| |
| if (nodePresentation != null) { |
| removeNodePresentation(nodePresentation); |
| } |
| } |
| }; |
| topologyRoot.accept(visitor); |
| } |
| |
| private MultiNodeListener getMultiNodeListener() { |
| if (this.multiNodeListener == null) { |
| this.multiNodeListener = new MultiNodeListener() { |
| @Override |
| protected void nodeAdded(GroupNode parent, Node nodeAdded) { |
| addNodeAndChildrens(nodeAdded); |
| } |
| |
| @Override |
| protected void nodesAdded(GroupNode parent, List<Node> nodesAdded) { |
| for (Node node : nodesAdded) { |
| addNodeAndChildrens(node); |
| } |
| } |
| |
| @Override |
| protected void nodeRemoved(GroupNode parent, Node nodeRemoved) { |
| removeNodeAndChildrens(nodeRemoved); |
| } |
| |
| @Override |
| protected void nodesRemoved(GroupNode parent, List<Node> nodesRemoved) { |
| for (Node node : nodesRemoved) { |
| removeNodeAndChildrens(node); |
| } |
| } |
| }; |
| } |
| return this.multiNodeListener; |
| } |
| |
| private List<TopologyPresentationSet> getAffectedTopologyPresentationSet(Node node) { |
| List<TopologyPresentationSet> topologyPresentationSetList = new ArrayList<TopologyPresentationSet>(); |
| |
| NodePresentation nodePresentation = getPresentationNode(node); |
| if (nodePresentation != null) { |
| topologyPresentationSetList.addAll(nodePresentation.getTopologyPresentationSet()); |
| } |
| |
| return topologyPresentationSetList; |
| } |
| |
| } // TopologyPresentationRegistryImpl |