package org.infoobject.magicmap.node.model;
import edu.uci.ics.jung.graph.Edge;
import edu.uci.ics.jung.graph.Vertex;
import edu.uci.ics.jung.graph.event.GraphEvent;
import edu.uci.ics.jung.graph.event.GraphEventListener;
import edu.uci.ics.jung.graph.event.GraphEventType;
import edu.uci.ics.jung.graph.impl.SparseGraph;
import edu.uci.ics.jung.graph.impl.UndirectedSparseEdge;
import edu.uci.ics.jung.graph.impl.UndirectedSparseGraph;
import edu.uci.ics.jung.graph.impl.UndirectedSparseVertex;
import edu.uci.ics.jung.utils.UserData;
import net.sf.magicmap.client.model.location.MagicGraphEvent;
import net.sf.magicmap.client.model.node.ClientNode;
import net.sf.magicmap.client.model.node.EdgeType;
import net.sf.magicmap.client.model.node.Node;
import net.sf.magicmap.client.model.node.NodeGraphListener;
import org.infoobject.core.infoobject.domain.InformationObject;
import org.infoobject.core.relation.domain.*;
import java.util.*;
/**
* <p>
* Class InformationNodeGraph ZUSAMMENFASSUNG
* </p>
* <p>
* DETAILS
* </p>
*
* @author Jan Friderici
* Date: 09.08.2008
* Time: 00:47:38
*/
public class InformationObjectNodeGraphImpl implements InformationObjectNodeGraph {
private final SparseGraph graph = new UndirectedSparseGraph();
private final Map<Node, Vertex> physicalNodes = new HashMap<Node, Vertex>();
private final Map<InformationObjectNode, Vertex> informationNodes = new HashMap<InformationObjectNode, Vertex>();
private final Map<RelationEdge, Edge> relations = new HashMap<RelationEdge, Edge>();
private final List<NodeGraphListener> listeners = Collections.synchronizedList(new ArrayList<NodeGraphListener>());
public InformationObjectNodeGraphImpl() {
graph.addListener(new GraphEventListener() {
public void vertexAdded(GraphEvent event) {
//To change body of implemented methods use File | Settings | File Templates.
}
public void vertexRemoved(GraphEvent event) {
}
public void edgeAdded(GraphEvent event) {
Edge e = (Edge) event.getGraphElement();
fireEdgAdded(getRelation(e));
}
public void edgeRemoved(GraphEvent event) {
Edge e = (Edge) event.getGraphElement();
fireEdgeRemoved(getRelation(e));
}
}, GraphEventType.ALL_SINGLE_EVENTS);
}
/**
*
* @param node
*/
public void insertNode(Node node) {
findVertex(node, true);
}
/**
* Dont use it. Neede only cause of api.
* @param n1
* @param n2
* @return
*/
@Deprecated
public RelationEdge addEdge(Node n1, Node n2) {
throw new IllegalStateException("Not suported");
}
public RelationEdge getRelation(Edge edge) {
return (RelationEdge) edge.getUserDatum("RELATION");
}
/**
*
* @param relationEdge
*/
public void updateRelation(RelationEdge relationEdge) {
double weight = relationEdge.getWeight();
if (weight == 0) {
removeEdge(relationEdge.getSourceNode(), relationEdge.getTargetNode());
// TODO notify;
} else {
// Todo notify change!
}
}
/**
*
* @param node
* @param createIfNotFound
* @return
*/
protected Vertex findVertex(Node node, boolean createIfNotFound) {
Vertex vertex = null;
if (node.isPhysical()) {
vertex = physicalNodes.get(node);
if (vertex == null){
vertex = new UndirectedSparseVertex();
vertex.setUserDatum("NODE", node, UserData.SHARED);
graph.addVertex(vertex);
physicalNodes.put(node,vertex);
}
} else if (node instanceof InformationObjectNode){
InformationObjectNode info = (InformationObjectNode) node;
vertex = informationNodes.get(info);
if (vertex == null) {
vertex = new UndirectedSparseVertex();
vertex.setUserDatum("NODE", info, UserData.SHARED);
graph.addVertex(vertex);
informationNodes.put(info,vertex);
}
} else if (createIfNotFound){
throw new IllegalArgumentException("Node type not supported " + node.getClass().getSimpleName());
}
return vertex;
}
/**
* @param node
* @param node1
* @return
*/
public RelationEdge getEdge(Node node, Node node1) {
final Vertex v1 = findVertex(node, false);
final Vertex v2 = findVertex(node1, false);
final Edge edge = (v1 != null && v2 != null) ? v1.findEdge(v2) : null;
return (RelationEdge) (edge != null ? edge.getUserDatum("RELATION") : null);
}
public PositionRelationEdge getObjectEdge(InformationObjectNode node, Node node1) {
final Vertex v1 = findVertex(node, false);
final Vertex v2 = findVertex(node1, false);
final Edge edge = (v1 != null && v2 != null) ? v1.findEdge(v2) : null;
return (PositionRelationEdge) (edge != null ? edge.getUserDatum("RELATION") : null);
}
public InformationRelationEdge getInformationEdge(InformationObjectNode node, InformationObjectNode node1) {
final Vertex v1 = findVertex(node, false);
final Vertex v2 = findVertex(node1, false);
final Edge edge = (v1 != null && v2 != null) ? v1.findEdge(v2) : null;
return (InformationRelationEdge) (edge != null ? edge.getUserDatum("RELATION") : null);
}
public boolean removeEdge(Node n1, Node n2) {
final Vertex v1 = findVertex(n1, false);
final Vertex v2 = findVertex(n2, false);
final Edge edge = (v1 != null && v2 != null) ? v1.findEdge(v2) : null;
if (edge != null) {
this.graph.removeEdge(edge);
this.relations.remove(getRelation(edge));
edge.removeUserDatum("RELATION");
return true;
}
return false;
}
public Set<? extends RelationEdge> getEdges(Node node) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public Set<? extends RelationEdge> getEdges() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
protected void fireEdgeRemoved(RelationEdge edge) {
MagicGraphEvent event = new MagicGraphEvent(this, edge);
for (NodeGraphListener l: getNodeGraphListeners()) {
l.edgeRemoved(event);
}
}
protected void fireEdgAdded(RelationEdge edge) {
MagicGraphEvent event = new MagicGraphEvent(this, edge);
for (NodeGraphListener l: getNodeGraphListeners()) {
l.edgeAdded(event);
}
}
public void addNodeGraphListener(NodeGraphListener nodeGraphListener) {
listeners.add(nodeGraphListener);
}
public void removeNodeGraphListener(NodeGraphListener nodeGraphListener) {
listeners.remove(nodeGraphListener);
}
public NodeGraphListener[] getNodeGraphListeners() {
return listeners.toArray(new NodeGraphListener[listeners.size()]);
}
public Collection<EdgeType> getSupportedEdgeTypes() {
return Collections.singletonList(new EdgeType("relation"));
}
/**
*
* @param n1
* @param n2
* @param factory
* @return
*/
public PositionRelationEdge addRelation(InformationObjectNode n1, Node n2, PositionRelation.Factory factory) {
if (n2 instanceof ClientNode) {
System.out.println("sourceNode = " + n2);
}
UndirectedSparseEdge edge = createJungEdge(n1, n2);
PositionRelationEdge relationEdge = (PositionRelationEdge) edge.getUserDatum("RELATION");
if (relationEdge == null) {
relationEdge = new PositionRelationEdge(n2, n1, this);
relationEdge.addRelation(factory.create(relationEdge));
edge.addUserDatum("RELATION", relationEdge, UserData.SHARED);
graph.addEdge(edge);
} else {
relationEdge.addRelation(factory.create(relationEdge));
}
return relationEdge;
}
public InformationRelationEdge addEdge(InformationObjectNode n1, InformationObjectNode n2, InformationRelation.Factory factory) {
UndirectedSparseEdge edge = createJungEdge(n1, n2);
InformationRelationEdge relationEdge = (InformationRelationEdge) edge.getUserDatum("RELATION");
if (relationEdge == null) {
relationEdge = new InformationRelationEdge(n1, n2, this);
relationEdge.addRelation(factory.create(relationEdge));
edge.addUserDatum("RELATION", relationEdge, UserData.SHARED);
this.relations.put(relationEdge, edge);
graph.addEdge(edge);
} else {
relationEdge.addRelation(factory.create(relationEdge));
}
return relationEdge;
}
private UndirectedSparseEdge createJungEdge(InformationObjectNode n1, Node n2) {
final Vertex v1 = findVertex(n1, false);
final Vertex v2 = findVertex(n2, false);
if (v1 == null || v2 == null) throw new IllegalArgumentException("No Vertex for nodes");
Edge e = v1.findEdge(v2);
return (UndirectedSparseEdge) (e != null ? e : new UndirectedSparseEdge(v1, v2));
}
/**
* @param information
* @return
*/
public Set<? extends RelationEdge> findRelations(InformationObject information) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
}