/*******************************************************************************
* 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:
* Generoso Pagano - initial API and implementation
******************************************************************************/
/**
*
*/
package fr.inria.soctrace.lib.query.hierarchy;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import fr.inria.soctrace.lib.model.EventProducer;
import fr.inria.soctrace.lib.model.utils.SoCTraceException;
import fr.inria.soctrace.lib.query.EventProducerQuery;
import fr.inria.soctrace.lib.storage.TraceDBObject;
/**
* Data structure the help the usage of Event Producer hierarchy.
*
* For a typical usage example see {@link TypicalUsage} source code.
*
* @author "Generoso Pagano <generoso.pagano@inria.fr>"
*/
public class EPHierarchyDescMap {
/**
* Map of descriptors, accessible by EP id.
*/
private Map<Integer, EPHierarchyDesc> descriptors = null;
/**
* Tree virtual root, to navigate the hierarchy as a tree.
*/
private EPHierarchyDesc root = null;
/**
* Constructor
*/
public EPHierarchyDescMap() {
root = new EPHierarchyDesc();
root.setEventProducer(null);
root.setRank(-1);
}
/**
* Get the descriptors map.
* Call one of the load methods before.
*
* @return the descriptor map
* @throws SoCTraceException
*/
public Map<Integer, EPHierarchyDesc> getHierarchyDescMap() throws SoCTraceException {
if (descriptors == null)
throw new SoCTraceException("Map not loaded!");
return descriptors;
}
/**
* Get the tree root.
* Note that this root is NOT an actual event producer,
* but a virtual root node (rank == -1)
*
* @return the root
* @throws SoCTraceException
*/
public EPHierarchyDesc getRoot() throws SoCTraceException {
if (descriptors == null)
throw new SoCTraceException("Map not loaded!");
return root;
}
/**
* Load the map with all the producers of the trace.
*
* @param traceDB trace DB
* @throws SoCTraceException
*/
public void load(TraceDBObject traceDB) throws SoCTraceException {
EventProducerQuery epq = new EventProducerQuery(traceDB);
List<EventProducer> eps = epq.getList();
load(eps);
epq.clear();
}
/**
* Load the map with the passed producers
*
* @param eps producers
*/
private void load(List<EventProducer> eps) {
descriptors = new HashMap<Integer, EPHierarchyDesc>();
// first put in the map, filling only the parent
for (EventProducer ep: eps) {
EPHierarchyDesc desc = new EPHierarchyDesc();
desc.setEventProducer(ep);
descriptors.put(ep.getId(), desc);
}
// fill the direct sons to have the tree
for (EventProducer ep: eps) {
EPHierarchyDesc desc = descriptors.get(ep.getId());
if (ep.getParentId() == EventProducer.NO_PARENT_ID) {
root.getDirectSons().add(desc);
} else {
EPHierarchyDesc parentDesc = descriptors.get(ep.getParentId());
parentDesc.getDirectSons().add(desc);
}
}
setRank(root, -1);
setDescendants(root);
}
/**
* Father fist visit to set rank
*/
private void setRank(EPHierarchyDesc desc, int rank) {
desc.setRank(rank);
for (EPHierarchyDesc d: desc.getDirectSons()) {
setRank(d, rank+1);
}
}
/**
* Leaves first visit to set descendants
*/
private void setDescendants(EPHierarchyDesc desc) {
// descendants are: my direct sons...
desc.getDescendants().addAll(desc.getDirectSons());
for (EPHierarchyDesc d: desc.getDirectSons()) {
setDescendants(d);
// ... and my sons' descendants
desc.getDescendants().addAll(d.getDescendants());
}
}
/**
* Print the map
* @throws SoCTraceException
*/
public void print() throws SoCTraceException {
getRoot().print("");
}
}