/*******************************************************************************
* Copyright 2012 University of Southern California
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This code was developed by the Information Integration Group as part
* of the Karma project at the Information Sciences Institute of the
* University of Southern California. For more information, publications,
* and related projects, please see: http://www.isi.edu/integration
******************************************************************************/
package edu.isi.karma.modeling.alignment;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashSet;
import java.util.Set;
import org.apache.log4j.Logger;
import org.jgrapht.DirectedGraph;
import org.jgrapht.Graph;
import org.jgrapht.UndirectedGraph;
import org.jgrapht.graph.DirectedWeightedMultigraph;
import edu.isi.karma.rep.alignment.ColumnNode;
import edu.isi.karma.rep.alignment.Link;
import edu.isi.karma.rep.alignment.Node;
public class GraphUtil {
private static Logger logger = Logger.getLogger(GraphUtil.class);
// FIXME: change methods to get an Outputstream as input and write on it.
private static String getNodeTypeString(Node node) {
if (node == null) {
System.out.println("node is null.");
return null;
}
String s = node.getClass().getName();
if (s.indexOf(".") != -1)
s = s.substring(s.lastIndexOf(".") + 1);
return s;
}
private static String getLinkTypeString(Link link) {
if (link == null) {
System.out.println("link is null.");
return null;
}
String s = link.getClass().getName();
if (s.indexOf(".") != -1)
s = s.substring(s.lastIndexOf(".") + 1);
return s;
}
public static void printVertex(Node node) {
if (node == null) {
System.out.println("node is null.");
return;
}
System.out.print("(");
System.out.print( node.getLocalId());
// System.out.print( vertex.getID());
System.out.print(", ");
if (node instanceof ColumnNode)
System.out.print( ((ColumnNode)node).getColumnName());
else
System.out.print(node.getLabel().getLocalName());
System.out.print(", ");
System.out.print(getNodeTypeString(node));
System.out.print(")");
}
public static void printEdge(Link link) {
if (link == null) {
System.out.println("link is null.");
return;
}
System.out.print("(");
System.out.print( link.getLocalId());
System.out.print(", ");
System.out.print(link.getLabel().getLocalName());
System.out.print(", ");
System.out.print(getLinkTypeString(link));
System.out.print(", ");
System.out.print(link.getWeight());
System.out.print(") - From ");
printVertex(link.getSource());
System.out.print(" To ");
printVertex(link.getTarget());
}
public static DirectedGraph<Node, Link> asDirectedGraph(UndirectedGraph<Node, Link> undirectedGraph) {
if (undirectedGraph == null) {
System.out.println("graph is null.");
return null;
}
DirectedGraph<Node, Link> g = new DirectedWeightedMultigraph<Node, Link>(Link.class);
for (Node v : undirectedGraph.vertexSet())
g.addVertex(v);
for (Link e: undirectedGraph.edgeSet())
g.addEdge(e.getSource(), e.getTarget(), e);
return g;
}
public static void printGraph(Graph<Node, Link> graph) {
if (graph == null) {
System.out.println("graph is null.");
return;
}
System.out.println("*** Nodes ***");
for (Node vertex : graph.vertexSet()) {
printVertex(vertex);
System.out.println();
}
System.out.println("*** Links ***");
for (Link edge : graph.edgeSet()) {
printEdge(edge);
System.out.println();
}
System.out.println("------------------------------------------");
}
public static void printGraphSimple(Graph<Node, Link> graph) {
if (graph == null) {
System.out.println("The input graph is null.");
return;
}
for (Link edge : graph.edgeSet()) {
System.out.print("(");
// if (edge.getSource() instanceof ColumnNode)
// System.out.print(edge.getSource().getLocalId() + "-" + ((ColumnNode)edge.getSource()).getColumnName());
// else
// System.out.print(edge.getSource().getLocalId());
// System.out.print(")");
// System.out.print(" - ");
// System.out.print("(");
System.out.print(edge.getId());
// System.out.print(")");
// System.out.print(" - ");
// System.out.print("(");
// if (edge.getTarget() instanceof ColumnNode)
// System.out.print(edge.getTarget().getLocalId() + "-" + ((ColumnNode)edge.getTarget()).getColumnName());
// else
// System.out.print(edge.getTarget().getLocalId());
// System.out.print(")");
System.out.print(" - status=" + edge.getStatus().name());
System.out.print(" - w=" + edge.getWeight());
System.out.println();
}
System.out.println("------------------------------------------");
}
@SuppressWarnings("unchecked")
public static DirectedWeightedMultigraph<Node, Link> treeToRootedTree(
DirectedWeightedMultigraph<Node, Link> tree, Node root, Set<String> reversedLinks, Set<String> removedLinks) {
if (tree == null) {
logger.error("The input tree is null.");
return null;
}
DirectedWeightedMultigraph<Node, Link> rootedTree =
(DirectedWeightedMultigraph<Node, Link>)tree.clone();
if (reversedLinks == null)
reversedLinks = new HashSet<String>();
if (removedLinks == null)
removedLinks = new HashSet<String>();
treeToRootedTree(rootedTree, root, null, new HashSet<Node>(), reversedLinks, removedLinks);
logger.info("model after converting to a rooted tree: ");
printGraphSimple(rootedTree);
logger.info("reversed links:");
for (String s : reversedLinks)
System.out.println("\t" + s);
logger.info("removed links:");
for (String s : removedLinks)
System.out.println("\t" + s);
return rootedTree;
}
public static void serialize(DirectedWeightedMultigraph<Node, Link> graph, String fileName) throws Exception
{
if (graph == null) {
logger.error("The input graph is null.");
return;
}
// ByteArrayOutputStream bout = new ByteArrayOutputStream();
FileOutputStream f = new FileOutputStream(fileName);
ObjectOutputStream out = new ObjectOutputStream(f);
out.writeObject(graph);
out.flush();
out.close();
}
@SuppressWarnings("unchecked")
public static DirectedWeightedMultigraph<Node, Link> deserialize(String fileName) throws Exception
{
// ByteArrayOutputStream bout = new ByteArrayOutputStream();
FileInputStream f = new FileInputStream(fileName);
ObjectInputStream in = new ObjectInputStream(f);
Object obj = in.readObject();
in.close();
if (obj instanceof DirectedWeightedMultigraph<?, ?>)
return (DirectedWeightedMultigraph<Node, Link>)obj;
else
return null;
}
private static void treeToRootedTree(DirectedWeightedMultigraph<Node, Link> tree, Node node, Link e, Set<Node> visitedNodes, Set<String> reversedLinks, Set<String> removedLinks) {
if (node == null)
return;
if (visitedNodes.contains(node)) // prevent having loop in the tree
return;
visitedNodes.add(node);
Node source, target;
Set<Link> incomingLinks = tree.incomingEdgesOf(node);
if (incomingLinks != null) {
Link[] incomingLinksArr = incomingLinks.toArray(new Link[0]);
for (Link inLink : incomingLinksArr) {
source = inLink.getSource();
target = inLink.getTarget();
// don't remove the incoming link from parent to this node
if (e != null && inLink.equals(e))
continue;
// removeEdge method should always be called before addEdge because the new edge has the same id
// and JGraph does not add the duplicate link
// Label label = new Label(inLink.getLabel().getUri(), inLink.getLabel().getNs(), inLink.getLabel().getPrefix());
Link reverseLink = inLink.clone(); //new Link(inLink.getId(), label);
tree.removeEdge(inLink);
tree.addEdge(target, source, reverseLink);
tree.setEdgeWeight(reverseLink, inLink.getWeight());
// Save the reversed links information
reversedLinks.add(inLink.getId());
}
}
Set<Link> outgoingLinks = tree.outgoingEdgesOf(node);
if (outgoingLinks == null)
return;
Link[] outgoingLinksArr = outgoingLinks.toArray(new Link[0]);
for (Link outLink : outgoingLinksArr) {
target = outLink.getTarget();
if (visitedNodes.contains(target)) {
tree.removeEdge(outLink);
removedLinks.add(outLink.getId());
} else {
treeToRootedTree(tree, target, outLink, visitedNodes, reversedLinks, removedLinks);
}
}
}
}