package gov.nih.ncgc.bard.capextract; import java.io.Serializable; import java.math.BigInteger; import java.util.HashSet; import java.util.Set; /** * The CAP dictionary represented as a directed graph. * <p/> * Each node is a {@link CAPDictionaryElement} and has two sets of edges, * incoming (analogous to parent relationships) and outgoing (analogous to * child relationships). A node is considered a <i>leaf</i> if it has no * outgoing edges. * * @author Rajarshi Guha */ public class CAPDictionary implements Serializable { static final long serialVersionUID = 5435103181432997247L; Set<CAPDictionaryElement> nodes; Set<Edge> inEdges, outEdges; public CAPDictionary() { nodes = new HashSet<CAPDictionaryElement>(); outEdges = new HashSet<Edge>(); inEdges = new HashSet<Edge>(); } public void addNode(CAPDictionaryElement node) { nodes.add(node); } /** * Create an edge in the graph. * * @param parent a node (analogous to parent). If node does not exists in the node list, it is added. * @param child a node (analogous to child). If node does not exists in the node list, it is added. * @param data arbitrary data to be associated with the outgoing edge */ public void addOutgoingEdge(CAPDictionaryElement parent, CAPDictionaryElement child, Object data) { if (!nodes.contains(parent)) addNode(parent); if (!nodes.contains(child)) addNode(child); outEdges.add(new Edge(parent, child, data)); } public void addIncomingEdge(CAPDictionaryElement child, CAPDictionaryElement parent, Object data) { if (!nodes.contains(child)) addNode(child); if (!nodes.contains(parent)) addNode(parent); inEdges.add(new Edge(child, parent, data)); } public Set<CAPDictionaryElement> getNodes() { return nodes; } public CAPDictionaryElement getNode(String label) { for (CAPDictionaryElement node : nodes) { if (node.getLabel().equals(label)) return node; } return null; } public CAPDictionaryElement getNode(BigInteger id) { if (nodes == null || id == null) return null; for (CAPDictionaryElement node : nodes) { if (node.getElementId() != null && node.getElementId().equals(id)) return node; } return null; } public Set<CAPDictionaryElement> getChildren(BigInteger nodeId) { return getChildren(getNode(nodeId)); } public Set<CAPDictionaryElement> getChildren(String label) { return getChildren(getNode(label)); } /** * Is this a lead node (i.e., no child nodes). * * @param node the node in question * @return true if a lead node, false otherwise */ public boolean isLeaf(CAPDictionaryElement node) { return getChildren(node).size() == 0; } public Set<CAPDictionaryElement> getChildren(CAPDictionaryElement node) { // just look at the outgoing edges Set<CAPDictionaryElement> children = new HashSet<CAPDictionaryElement>(); for (Edge e : outEdges) { if (e.from.equals(node)) children.add(e.to); } return children; } public Set<CAPDictionaryElement> getParents(String label) { return getParents(getNode(label)); } public Set<CAPDictionaryElement> getParents(BigInteger nodeId) { return getParents(getNode(nodeId)); } public Set<CAPDictionaryElement> getParents(CAPDictionaryElement node) { // just look at the outgoing edges Set<CAPDictionaryElement> parents = new HashSet<CAPDictionaryElement>(); for (Edge e : inEdges) { if (e.from.equals(node)) parents.add(e.to); } return parents; } public int size() { return nodes.size(); } class Edge implements Serializable { static final long serialVersionUID = -964324348571286627L; CAPDictionaryElement from, to; Object data; Edge(CAPDictionaryElement from, CAPDictionaryElement to) { this.from = from; this.to = to; data = null; } Edge(CAPDictionaryElement from, CAPDictionaryElement to, Object data) { this.from = from; this.to = to; this.data = data; } @Override public boolean equals(Object o) { if (!(o instanceof Edge)) return false; Edge e = (Edge) o; return e.from == from && e.to == to && e.data == data; } } }