/******************************************************************************* * Copyright (c) 2012-2015 INRIA. * 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: * Damien Dosimont <damien.dosimont@imag.fr> * Youenn Corre <youenn.corret@inria.fr> ******************************************************************************/ package fr.inria.soctrace.tools.ocelotl.core.model; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import fr.inria.soctrace.framesoc.ui.utils.AlphanumComparator; import fr.inria.soctrace.lib.model.EventProducer; public class SimpleEventProducerHierarchy { public class SimpleEventProducerNode { private int id; private String name; private EventProducer me; private SimpleEventProducerNode parentNode; private List<SimpleEventProducerNode> childrenNodes = new ArrayList<SimpleEventProducerNode>(); // Depth in the hierarchy level of the node (the smaller, the higher // in the hierarchy) private int hierarchyLevel; public SimpleEventProducerNode() { me = null; id = -1; name = "abstractRootNode"; hierarchyLevel = 0; } public SimpleEventProducerNode(EventProducer ep) { me = ep; id = me.getId(); epnIndex.put(ep, this); name = me.getName(); orphans.put(id, this); leaves.put(id, this); setParent(); } public int getID() { return id; } private void setParent() { if (!eventProducerNodes.containsKey(me.getParentId())) { // If parent exists if (eventProducers.containsKey(me.getParentId()) && me.getId() != me.getParentId()) { eventProducerNodes.put( me.getParentId(), new SimpleEventProducerNode(eventProducers.get(me .getParentId()))); } else { // It is a root parentNode = root; root.addChild(this); orphans.remove(id); return; } } parentNode = eventProducerNodes.get(me.getParentId()); parentNode.addChild(this); orphans.remove(id); hierarchyLevel = parentNode.getHierarchyLevel() + 1; if(hierarchyLevel > maxHierarchyLevel) maxHierarchyLevel = hierarchyLevel; } public void addChild(SimpleEventProducerNode child) { childrenNodes.add(child); if (leaves.containsKey(id)) leaves.remove(id); } public EventProducer getMe() { return me; } public SimpleEventProducerNode getParentNode() { return parentNode; } public List<SimpleEventProducerNode> getChildrenNodes() { return childrenNodes; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getHierarchyLevel() { return hierarchyLevel; } public void setHierarchyLevel(int hierarchyLevel) { this.hierarchyLevel = hierarchyLevel; } /** * Sort the children node and all its children */ public void sortChildrenNodes() { Collections.sort(childrenNodes, new Comparator<SimpleEventProducerNode>() { @Override public int compare(SimpleEventProducerNode o1, SimpleEventProducerNode o2) { return AlphanumComparator.compare(o1.getMe() .getName(), o2.getMe().getName()); } }); for (SimpleEventProducerNode aChildNode : childrenNodes) { aChildNode.sortChildrenNodes(); } } public void destroy() { for (SimpleEventProducerNode child : childrenNodes) { child.destroy(); } eventProducerNodes.remove(id); if (orphans.containsKey(id)) orphans.remove(id); if (leaves.containsKey(id)) leaves.remove(id); eventProducers.remove(id); childrenNodes.clear(); } } private Map<Integer, SimpleEventProducerNode> eventProducerNodes = new HashMap<Integer, SimpleEventProducerNode>(); private Map<EventProducer, SimpleEventProducerNode> epnIndex = new HashMap<EventProducer, SimpleEventProducerNode>(); private Map<Integer, SimpleEventProducerNode> orphans = new HashMap<Integer, SimpleEventProducerNode>(); private Map<Integer, SimpleEventProducerNode> leaves = new HashMap<Integer, SimpleEventProducerNode>(); private Map<Integer, EventProducer> eventProducers = new HashMap<Integer, EventProducer>(); private static final Logger logger = LoggerFactory.getLogger(SimpleEventProducerHierarchy.class); protected int maxHierarchyLevel; /** * Used as an abstract root node since the hierarchy might have several top-level node */ private SimpleEventProducerNode root = null; public SimpleEventProducerHierarchy(List<EventProducer> eventProducers) { super(); for (EventProducer ep : eventProducers) { this.eventProducers.put(ep.getId(), ep); } root = new SimpleEventProducerNode(); maxHierarchyLevel = 0; setHierarchy(); } private void setHierarchy() { for (EventProducer ep : eventProducers.values()) { if (!eventProducerNodes.containsKey(ep.getId())) eventProducerNodes.put(ep.getId(), new SimpleEventProducerNode(ep)); } root.sortChildrenNodes(); if (!orphans.isEmpty()) { logger.error("Error: The event producer hierarchy contains elements without a parent."); for (Integer orphan : orphans.keySet()) { if (orphans.containsKey(orphan)) orphans.get(orphan).destroy(); } } } public Map<Integer, SimpleEventProducerNode> getEventProducerNodes() { return eventProducerNodes; } public Map<Integer, SimpleEventProducerNode> getLeaves() { return leaves; } public Map<Integer, SimpleEventProducerNode> getNodes() { Map<Integer, SimpleEventProducerNode> nodes = new HashMap<Integer, SimpleEventProducerNode>(); for (int id : eventProducerNodes.keySet()) { if (!leaves.containsKey(id) && root.getID() != id) nodes.put(id, eventProducerNodes.get(id)); } return nodes; } public Map<Integer, EventProducer> getEventProducers() { return eventProducers; } public SimpleEventProducerNode getRoot() { return root; } public int getMaxHierarchyLevel() { return maxHierarchyLevel; } public void setMaxHierarchyLevel(int maxHierarchyLevel) { this.maxHierarchyLevel = maxHierarchyLevel; } public Map<EventProducer, SimpleEventProducerNode> getEpnIndex() { return epnIndex; } public void setEpnIndex(Map<EventProducer, SimpleEventProducerNode> epnIndex) { this.epnIndex = epnIndex; } public int getParentID(int id) { return eventProducerNodes.get(id).getParentNode().getID(); } /** * Check if an event producer is a leaf * * @param ep * the tested event producer * @return true if it is a leaf, false otherwise */ public boolean isLeaf(EventProducer ep) { for (SimpleEventProducerNode sepn : leaves.values()) if (sepn.getMe().getId() == ep.getId()) return true; return false; } /** * Get all the producer nodes of a given level of hierarchy * * @param hierarchyLevel * the wanted hierarchy level * @return the list of corresponding event producer nodes */ public ArrayList<SimpleEventProducerNode> getEventProducerNodesFromHierarchyLevel( int hierarchyLevel) { ArrayList<SimpleEventProducerNode> selectedEpn = new ArrayList<SimpleEventProducerNode>(); for (SimpleEventProducerNode epn : eventProducerNodes.values()) { if (epn.getHierarchyLevel() == hierarchyLevel) selectedEpn.add(epn); } return selectedEpn; } /** * Get leaf producers that are under a given node in the hierarchy * * @param aNode * the node from which we want to get the leaves * @return the leaves */ public ArrayList<SimpleEventProducerNode> getLeaves( SimpleEventProducerNode aNode) { ArrayList<SimpleEventProducerNode> theLeaves = new ArrayList<SimpleEventProducerNode>(); for (SimpleEventProducerNode aLeaf : leaves.values()) { SimpleEventProducerNode parent = aLeaf.getParentNode(); while (parent != aNode && parent != root && parent != null) { parent = parent.getParentNode(); } if (parent == aNode) theLeaves.add(aLeaf); } return theLeaves; } /** * Recursively get all the children node (down to the leaves) of a node * * @param aNode * the node from which we want all children * @return a collection containing all the children of a node plus itself */ public ArrayList<SimpleEventProducerNode> getAllChildrenNodes( SimpleEventProducerNode aNode) { ArrayList<SimpleEventProducerNode> children = new ArrayList<SimpleEventProducerNode>(); children.add(aNode); for (SimpleEventProducerNode aChild : aNode.getChildrenNodes()) { children.addAll(getAllChildrenNodes(aChild)); } return children; } }