/******************************************************************************* * 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.File; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map.Entry; import java.util.Set; import org.apache.log4j.Logger; import org.jgrapht.graph.DirectedWeightedMultigraph; import edu.isi.karma.modeling.ModelingParams; import edu.isi.karma.modeling.Namespaces; import edu.isi.karma.modeling.Prefixes; import edu.isi.karma.modeling.Uris; import edu.isi.karma.modeling.ontology.OntologyManager; import edu.isi.karma.rep.alignment.ColumnNode; import edu.isi.karma.rep.alignment.DataPropertyLink; import edu.isi.karma.rep.alignment.InternalNode; import edu.isi.karma.rep.alignment.Label; import edu.isi.karma.rep.alignment.Link; import edu.isi.karma.rep.alignment.LinkPriorityType; import edu.isi.karma.rep.alignment.LinkStatus; import edu.isi.karma.rep.alignment.LinkType; import edu.isi.karma.rep.alignment.Node; import edu.isi.karma.rep.alignment.NodeType; import edu.isi.karma.rep.alignment.ObjectPropertyLink; import edu.isi.karma.rep.alignment.SimpleLink; import edu.isi.karma.rep.alignment.SubClassLink; public class GraphBuilder { static Logger logger = Logger.getLogger(GraphBuilder.class); private DirectedWeightedMultigraph<Node, Link> graph; private OntologyManager ontologyManager; private NodeIdFactory nodeIdFactory; // private LinkIdFactory linkIdFactory; private HashSet<String> visitedSourceTargetPairs; private HashSet<String> sourceToTargetLinkUris; private HashSet<String> sourceToTargetConnectivity; private Node thingNode; // HashMaps private HashMap<String, Node> idToNodeMap; private HashMap<String, Link> idToLinkMap; private HashMap<String, List<Node>> uriToNodesMap; private HashMap<String, List<Link>> uriToLinksMap; private HashMap<NodeType, List<Node>> typeToNodesMap; private HashMap<LinkType, List<Link>> typeToLinksMap; private HashMap<LinkStatus, List<Link>> statusToLinksMap; // used for deleting a node private HashMap<Node, Integer> nodeReferences; private HashMap<String, List<String>> uriClosure; // Constructor public GraphBuilder(OntologyManager ontologyManager, NodeIdFactory nodeIdFactory) { //, LinkIdFactory linkIdFactory) { this.ontologyManager = ontologyManager; this.nodeIdFactory = nodeIdFactory; // this.linkIdFactory = linkIdFactory; this.idToNodeMap = new HashMap<String, Node>(); this.idToLinkMap = new HashMap<String, Link>(); this.uriToNodesMap = new HashMap<String, List<Node>>(); this.uriToLinksMap = new HashMap<String, List<Link>>(); this.typeToNodesMap = new HashMap<NodeType, List<Node>>(); this.typeToLinksMap = new HashMap<LinkType, List<Link>>(); this.statusToLinksMap = new HashMap<LinkStatus, List<Link>>(); this.nodeReferences = new HashMap<Node, Integer>(); this.uriClosure = new HashMap<String, List<String>>(); this.graph = new DirectedWeightedMultigraph<Node, Link>(Link.class); this.visitedSourceTargetPairs = new HashSet<String>(); this.sourceToTargetLinkUris = new HashSet<String>(); this.sourceToTargetConnectivity = new HashSet<String>(); this.initialGraph(); logger.info("initial graph has been created."); } public GraphBuilder(OntologyManager ontologyManager, DirectedWeightedMultigraph<Node, Link> graph) { this.graph = graph; this.ontologyManager = ontologyManager; this.idToNodeMap = new HashMap<String, Node>(); this.idToLinkMap = new HashMap<String, Link>(); this.uriToNodesMap = new HashMap<String, List<Node>>(); this.uriToLinksMap = new HashMap<String, List<Link>>(); this.typeToNodesMap = new HashMap<NodeType, List<Node>>(); this.typeToLinksMap = new HashMap<LinkType, List<Link>>(); this.statusToLinksMap = new HashMap<LinkStatus, List<Link>>(); this.visitedSourceTargetPairs = new HashSet<String>(); this.sourceToTargetLinkUris = new HashSet<String>(); this.sourceToTargetConnectivity = new HashSet<String>(); this.nodeIdFactory = new NodeIdFactory(); // this.linkIdFactory = new LinkIdFactory(); for (Node node : this.graph.vertexSet()) { if (node instanceof InternalNode) nodeIdFactory.getNodeId(node.getLabel().getUri()); this.idToNodeMap.put(node.getId(), node); List<Node> nodesWithSameUri = uriToNodesMap.get(node.getLabel().getUri()); if (nodesWithSameUri == null) { nodesWithSameUri = new ArrayList<Node>(); uriToNodesMap.put(node.getLabel().getUri(), nodesWithSameUri); } nodesWithSameUri.add(node); List<Node> nodesWithSameType = typeToNodesMap.get(node.getType()); if (nodesWithSameType == null) { nodesWithSameType = new ArrayList<Node>(); typeToNodesMap.put(node.getType(), nodesWithSameType); } nodesWithSameType.add(node); } Node source; Node target; for (Link link : this.graph.edgeSet()) { source = link.getSource(); target = link.getTarget(); this.idToLinkMap.put(link.getId(), link); List<Link> linksWithSameUri = uriToLinksMap.get(link.getLabel().getUri()); if (linksWithSameUri == null) { linksWithSameUri = new ArrayList<Link>(); uriToLinksMap.put(link.getLabel().getUri(), linksWithSameUri); } linksWithSameUri.add(link); List<Link> linksWithSameStatus = statusToLinksMap.get(link.getStatus()); if (linksWithSameStatus == null) { linksWithSameStatus = new ArrayList<Link>(); statusToLinksMap.put(link.getStatus(), linksWithSameUri); } linksWithSameStatus.add(link); List<Link> linksWithSameType = typeToLinksMap.get(link.getType()); if (linksWithSameType == null) { linksWithSameType = new ArrayList<Link>(); typeToLinksMap.put(link.getType(), linksWithSameType); } linksWithSameType.add(link); String key = source.getId() + target.getId() + link.getLabel().getUri(); sourceToTargetLinkUris.add(key); this.visitedSourceTargetPairs.add(source.getId() + target.getId()); } this.nodeReferences = new HashMap<Node, Integer>(); this.uriClosure = new HashMap<String, List<String>>(); logger.info("graph has been loaded."); } public NodeIdFactory getNodeIdFactory() { return nodeIdFactory; } public boolean isConnected(String nodeId1, String nodeId2) { return this.sourceToTargetConnectivity.contains(nodeId1 + nodeId2); } // public LinkIdFactory getLinkIdFactory() { // return linkIdFactory; // } public OntologyManager getOntologyManager() { return this.ontologyManager; } public DirectedWeightedMultigraph<Node, Link> getGraph() { return this.graph; } public void setGraph(DirectedWeightedMultigraph<Node, Link> graph) { this.graph = graph; } public HashMap<String, Node> getIdToNodeMap() { return idToNodeMap; } public HashMap<String, Link> getIdToLinkMap() { return idToLinkMap; } public HashMap<String, List<Node>> getUriToNodesMap() { return uriToNodesMap; } public HashMap<String, List<Link>> getUriToLinksMap() { return uriToLinksMap; } public HashMap<NodeType, List<Node>> getTypeToNodesMap() { return typeToNodesMap; } public HashMap<LinkType, List<Link>> getTypeToLinksMap() { return typeToLinksMap; } public HashMap<LinkStatus, List<Link>> getStatusToLinksMap() { return statusToLinksMap; } public Node getThingNode() { return thingNode; } public void resetOntologyMaps() { String[] currentUris = this.uriClosure.keySet().toArray(new String[0]); this.uriClosure.clear(); for (String uri : currentUris) computeUriClosure(uri); } public void addNodeList(List<Node> nodes) { addNodeList(nodes, null); } public void addNodeList(List<Node> nodes, Set<Node> addedNodes) { logger.debug("<enter"); if (addedNodes == null) addedNodes = new HashSet<Node>(); long start = System.currentTimeMillis(); float elapsedTimeSec; for (Node node : nodes) { if (!addSingleNode(node)) continue; addedNodes.add(node); if (node instanceof InternalNode) { addNodeClosure(node, addedNodes); } } long addNodesClosure = System.currentTimeMillis(); elapsedTimeSec = (addNodesClosure - start)/1000F; logger.info("time to add nodes closure: " + elapsedTimeSec); updateLinks2(); long updateLinks = System.currentTimeMillis(); elapsedTimeSec = (updateLinks - addNodesClosure)/1000F; logger.info("time to update links of the graph: " + elapsedTimeSec); logger.info("total number of nodes in graph: " + this.graph.vertexSet().size()); logger.info("total number of links in graph: " + this.graph.edgeSet().size()); logger.debug("exit>"); } public boolean addNode(Node node) { return addNode(node, null); } public boolean addNode(Node node, Set<Node> addedNodes) { logger.debug("<enter"); if (addedNodes == null) addedNodes = new HashSet<Node>(); if (!addSingleNode(node)) return false; if (node instanceof InternalNode) { long start = System.currentTimeMillis(); float elapsedTimeSec; // List<Node> newNodes = new ArrayList<Node>(); // addNodeClosure(node, newNodes); // newNodes.add(node); // addNodeClosure(node, newNodes); addedNodes.add(node); addNodeClosure(node, addedNodes); long addNodesClosure = System.currentTimeMillis(); elapsedTimeSec = (addNodesClosure - start)/1000F; logger.info("time to add nodes closure: " + elapsedTimeSec); updateLinks2(); // updateLinks(); // if we consider the set of current nodes as S1 and the set of new added nodes as S2: // (*) the direction of all the subclass links between S1 and S2 is from S2 to S1 // This is because superclasses of all the nodes in S1 are already added to the graph. // (*) the direction of all the object property links between S1 and S2 is from S1 to S2 // This is because all the nodes that are reachable from S1 are added to the graph before adding new nodes in S2. long updateLinks = System.currentTimeMillis(); elapsedTimeSec = (updateLinks - addNodesClosure)/1000F; logger.info("time to update links of the graph: " + elapsedTimeSec); // updateLinksFromThing(); long updateLinksFromThing = System.currentTimeMillis(); elapsedTimeSec = (updateLinksFromThing - updateLinks)/1000F; logger.info("time to update links to Thing (root): " + elapsedTimeSec); logger.info("total number of nodes in graph: " + this.graph.vertexSet().size()); logger.info("total number of links in graph: " + this.graph.edgeSet().size()); } logger.debug("exit>"); return true; } public boolean addNodeWithoutUpdatingGraph(Node node) { logger.debug("<enter"); if (!addSingleNode(node)) return false; logger.debug("exit>"); return true; } public boolean addLink(Node source, Node target, Link link) { logger.debug("<enter"); if (source == null || target == null || link == null) { logger.error("Source, target, and the link cannot be null."); return false; } if (this.idToLinkMap.containsKey(link.getId())) { logger.debug("The link with id=" + link.getId() + " already exists in the graph"); return false; } String key = source.getId() + target.getId() + link.getLabel().getUri(); // check to see if the link is duplicate or not if (sourceToTargetLinkUris.contains(key)) { logger.debug("There is already a link with label " + link.getLabel().getUri() + " from " + source.getId() + " to " + target.getId()); return false; } this.graph.addEdge(source, target, link); this.sourceToTargetConnectivity.add(source.getId() + target.getId()); this.sourceToTargetConnectivity.add(target.getId() + source.getId()); double w = 0.0; if (link.getPriorityType() == LinkPriorityType.DirectDataProperty) w = ModelingParams.PROPERTY_DIRECT_WEIGHT; else if (link.getPriorityType() == LinkPriorityType.IndirectObjectProperty) w = ModelingParams.PROPERTY_INDIRECT_WEIGHT; else if (link.getPriorityType() == LinkPriorityType.ObjectPropertyWithOnlyDomain) w = ModelingParams.PROPERTY_WITH_ONLY_DOMAIN_WEIGHT; else if (link.getPriorityType() == LinkPriorityType.ObjectPropertyWithOnlyRange) w = ModelingParams.PROPERTY_WITH_ONLY_RANGE_WEIGHT; else if (link.getPriorityType() == LinkPriorityType.ObjectPropertyWithoutDomainAndRange) w = ModelingParams.PROPERTY_WITHOUT_DOMAIN_RANGE_WEIGHT; else if (link.getPriorityType() == LinkPriorityType.SubClassOf) w = ModelingParams.SUBCLASS_WEIGHT; else w = ModelingParams.PROPERTY_DIRECT_WEIGHT; this.graph.setEdgeWeight(link, w); // update the corresponding lists and hashmaps this.idToLinkMap.put(link.getId(), link); List<Link> linksWithSameUri = uriToLinksMap.get(link.getLabel().getUri()); if (linksWithSameUri == null) { linksWithSameUri = new ArrayList<Link>(); uriToLinksMap.put(link.getLabel().getUri(), linksWithSameUri); } linksWithSameUri.add(link); // if (link.getId().equals("http://km.aifb.kit.edu/projects/d3/cruiser#Vehicle1---http://km.aifb.kit.edu/projects/d3/cruiser#at---http://www.w3.org/2003/01/geo/wgs84_pos#Point1")) // System.out.println("debug1"); changeLinkStatus(link, link.getStatus()); List<Link> linksWithSameType = typeToLinksMap.get(link.getType()); if (linksWithSameType == null) { linksWithSameType = new ArrayList<Link>(); typeToLinksMap.put(link.getType(), linksWithSameType); } linksWithSameType.add(link); sourceToTargetLinkUris.add(key); if (source instanceof InternalNode && target instanceof ColumnNode) { List<Node> closure = this.getNodeClosure(source); List<Node> closureIncludingSelf = new ArrayList<Node>(); if (closure != null) closureIncludingSelf.addAll(closure); if (!closureIncludingSelf.contains(source)) closureIncludingSelf.add(source); for (Node n : closureIncludingSelf) { Integer refCount = this.nodeReferences.get(n); if (refCount != null) this.nodeReferences.put(n, ++refCount); } } logger.debug("exit>"); return true; } public void changeLinkStatus(Link link, LinkStatus newStatus) { // if (link.getId().equals("http://km.aifb.kit.edu/projects/d3/cruiser#Vehicle1---http://km.aifb.kit.edu/projects/d3/cruiser#at---http://www.w3.org/2003/01/geo/wgs84_pos#Point1")) // System.out.println("debug3"); LinkStatus oldStatus = link.getStatus(); // if (newStatus == oldStatus) // return; link.setStatus(newStatus); List<Link> linksWithOldStatus = this.statusToLinksMap.get(oldStatus); if (linksWithOldStatus != null) linksWithOldStatus.remove(link); List<Link> linksWithNewStatus = this.statusToLinksMap.get(newStatus); if (linksWithNewStatus == null) { linksWithNewStatus = new ArrayList<Link>(); statusToLinksMap.put(newStatus, linksWithNewStatus); } linksWithNewStatus.add(link); } public void changeLinkWeight(Link link, double weight) { this.graph.setEdgeWeight(link, weight); } public boolean removeLink(Link link) { if (link == null) { logger.debug("The link is null."); return false; } if (idToLinkMap.get(link.getId()) == null) { logger.debug("The link with id=" + link.getId() + " does not exists in the graph."); return false; } Node source = link.getSource(); Node target = link.getTarget(); if (source instanceof InternalNode && target instanceof ColumnNode) { List<Node> closure = this.getNodeClosure(source); List<Node> closureIncludingSelf = new ArrayList<Node>(); if (closure != null) closureIncludingSelf.addAll(closure); if (!closureIncludingSelf.contains(source)) closureIncludingSelf.add(source); for (Node n : closureIncludingSelf) { Integer refCount = this.nodeReferences.get(n); if (refCount != null) this.nodeReferences.put(n, --refCount); } } if (!removeSingleLink(link)) return false; return true; } public boolean removeNode(Node node) { if (node == null) { logger.debug("The node is null"); return false; } if (idToNodeMap.get(node.getId()) == null) { logger.debug("The node with id=" + node.getId() + " does not exists in the graph."); return false; } List<Node> closure = this.getNodeClosure(node); List<Node> closureIncludingSelf = new ArrayList<Node>(); if (closure != null) closureIncludingSelf.addAll(closure); if (!closureIncludingSelf.contains(node)) closureIncludingSelf.add(node); for (Node n : closureIncludingSelf) { Integer refCount = this.nodeReferences.get(n); if (refCount != null) { if (refCount.intValue() == 0) removeSingleNode(n); else this.nodeReferences.put(n, --refCount); } } logger.info("total number of nodes in graph: " + this.graph.vertexSet().size()); logger.info("total number of links in graph: " + this.graph.edgeSet().size()); return true; } public void updateGraph() { updateGraph(null); } public void updateGraph(Set<Node> addedNodes) { logger.debug("<enter"); if (addedNodes == null) addedNodes = new HashSet<Node>(); long start = System.currentTimeMillis(); float elapsedTimeSec; List<Node> internalNodes = this.typeToNodesMap.get(NodeType.InternalNode); if (internalNodes != null) { Node[] nodes = internalNodes.toArray(new Node[0]); for (Node node : nodes) addNodeClosure(node, addedNodes); } long addNodesClosure = System.currentTimeMillis(); elapsedTimeSec = (addNodesClosure - start)/1000F; logger.info("time to add nodes closure: " + elapsedTimeSec); updateLinks2(); long updateLinks = System.currentTimeMillis(); elapsedTimeSec = (updateLinks - addNodesClosure)/1000F; logger.info("time to update links of the graph: " + elapsedTimeSec); // updateLinksFromThing(); // long updateLinksFromThing = System.currentTimeMillis(); // elapsedTimeSec = (updateLinksFromThing - updateLinks)/1000F; // logger.info("time to update links to Thing (root): " + elapsedTimeSec); logger.info("total number of nodes in graph: " + this.graph.vertexSet().size()); logger.info("total number of links in graph: " + this.graph.edgeSet().size()); logger.debug("exit>"); } // Private Methods private void initialGraph() { logger.debug("<enter"); // Add Thing to the Graph String id = nodeIdFactory.getNodeId(Uris.THING_URI); Label label = new Label(Uris.THING_URI, Namespaces.OWL, Prefixes.OWL); thingNode = new InternalNode(id, label); addSingleNode(thingNode); logger.debug("exit>"); } private boolean addSingleNode(Node node) { logger.debug("<enter"); if (node == null) { logger.debug("The node is null."); return false; } if (idToNodeMap.get(node.getId()) != null) { logger.debug("The node with id=" + node.getId() + " already exists in the graph."); return false; } this.graph.addVertex(node); this.idToNodeMap.put(node.getId(), node); List<Node> nodesWithSameUri = uriToNodesMap.get(node.getLabel().getUri()); if (nodesWithSameUri == null) { nodesWithSameUri = new ArrayList<Node>(); uriToNodesMap.put(node.getLabel().getUri(), nodesWithSameUri); } nodesWithSameUri.add(node); List<Node> nodesWithSameType = typeToNodesMap.get(node.getType()); if (nodesWithSameType == null) { nodesWithSameType = new ArrayList<Node>(); typeToNodesMap.put(node.getType(), nodesWithSameType); } nodesWithSameType.add(node); this.nodeReferences.put(node, 0); logger.debug("exit>"); return true; } private boolean removeSingleNode(Node node) { logger.debug("<enter"); Set<Link> incomingLinks = this.graph.incomingEdgesOf(node); if (incomingLinks != null) { Link[] incomingLinksArray = incomingLinks.toArray(new Link[0]); for (Link inLink: incomingLinksArray) { this.removeSingleLink(inLink); } } Set<Link> outgoingLinks = this.graph.outgoingEdgesOf(node); if (outgoingLinks != null) { Link[] outgoingLinksArray = outgoingLinks.toArray(new Link[0]); for (Link outLink: outgoingLinksArray) { this.removeSingleLink(outLink); } } if (!this.graph.removeVertex(node)) return false; // updating hashmaps this.idToNodeMap.remove(node.getId()); List<Node> nodesWithSameUri = uriToNodesMap.get(node.getLabel().getUri()); if (nodesWithSameUri != null) nodesWithSameUri.remove(node); List<Node> nodesWithSameType = typeToNodesMap.get(node.getType()); if (nodesWithSameType != null) nodesWithSameType.remove(node); this.nodeReferences.remove(node); logger.debug("exit>"); return true; } private boolean removeSingleLink(Link link) { if (!this.graph.removeEdge(link)) return false; // update hashmaps this.idToLinkMap.remove(link.getId()); List<Link> linksWithSameUri = uriToLinksMap.get(link.getLabel().getUri()); if (linksWithSameUri != null) linksWithSameUri.remove(link); List<Link> linksWithSameType = typeToLinksMap.get(link.getType()); if (linksWithSameType != null) linksWithSameType.remove(link); List<Link> linksWithSameStatus = statusToLinksMap.get(link.getStatus()); if (linksWithSameStatus != null) linksWithSameStatus.remove(link); this.sourceToTargetLinkUris.remove(link.getSource().getId() + link.getTarget().getId() + link.getLabel().getUri()); return true; } private HashSet<String> getUriDirectConnections(String uri) { HashSet<String> uriDirectConnections = new HashSet<String>(); HashSet<String> opDomainClasses = null; HashMap<String, Label> superClasses = null; // We don't need to add subclasses of each class separately. // The only place in which we add children is where we are looking for domain class of a property. // In this case, in addition to the domain class, we add all of its children too. opDomainClasses = ontologyManager.getDomainsGivenRange(uri, true); superClasses = ontologyManager.getSuperClasses(uri, false); if (opDomainClasses != null) uriDirectConnections.addAll(opDomainClasses); if (superClasses != null) uriDirectConnections.addAll(superClasses.keySet()); return uriDirectConnections; } private List<String> computeUriClosure(String uri) { List<String> closure = this.uriClosure.get(uri); if (closure != null) return closure; closure = new ArrayList<String>(); List<String> closedList = new ArrayList<String>(); HashMap<String, List<String>> dependentUrisMap = new HashMap<String, List<String>>(); computeUriClosureRecursive(uri, closure, closedList, dependentUrisMap); if (closedList.contains(uri) && !closure.contains(uri)) closure.add(uri); int count = 1; while (count != 0) { count = 0; for (String s : dependentUrisMap.keySet()) { List<String> temp = this.uriClosure.get(s); List<String> dependentUris = dependentUrisMap.get(s); for (String ss : dependentUris) { if (!temp.contains(ss)) { temp.add(ss); count++;} if (this.uriClosure.get(ss) != null) { String[] cc = this.uriClosure.get(ss).toArray(new String[0]); for (String c : cc) { if (!temp.contains(c)) {temp.add(c); count++;} } } } } } return closure; } private void computeUriClosureRecursive(String uri, List<String> closure, List<String> closedList, HashMap<String, List<String>> dependentUrisMap) { logger.debug("<enter"); closedList.add(uri); List<String> currentClosure = this.uriClosure.get(uri); if (currentClosure != null) { closure.addAll(currentClosure); return; } HashSet<String> uriDirectConnections = getUriDirectConnections(uri); if (uriDirectConnections.size() == 0) { this.uriClosure.put(uri, new ArrayList<String>()); } else { for (String c : uriDirectConnections) { if (closedList.contains(c)) { List<String> dependentUris = dependentUrisMap.get(uri); if (dependentUris == null) { dependentUris = new ArrayList<String>(); dependentUrisMap.put(uri, dependentUris); } if (!dependentUris.contains(c)) dependentUris.add(c); continue; } if (!closure.contains(c)) closure.add(c); if (!closedList.contains(c)) closedList.add(c); List<String> localClosure = new ArrayList<String>(); computeUriClosureRecursive(c, localClosure, closedList, dependentUrisMap); for (String s : localClosure) if (!closure.contains(s)) closure.add(s); } this.uriClosure.put(uri, closure); } logger.debug("exit>"); } private List<Node> getNodeClosure(Node node) { List<Node> nodeClosure = new ArrayList<Node>(); if (node instanceof ColumnNode) return nodeClosure; String uri = node.getLabel().getUri(); List<String> closure = this.uriClosure.get(uri); if (closure == null) { // the closure has already been computed. closure = computeUriClosure(uri); } for (String s : closure) { List<Node> nodes = uriToNodesMap.get(s); if (nodes != null) nodeClosure.addAll(nodes); } return nodeClosure; } /** * returns all the new nodes that should be added to the graph due to adding the input node * @param node * @param closure: contains all the nodes that are connected to the input node * by ObjectProperty or SubClass links * @return */ private void addNodeClosure(Node node, Set<Node> newAddedNodes) { logger.debug("<enter"); if (newAddedNodes == null) newAddedNodes = new HashSet<Node>(); String uri = node.getLabel().getUri(); List<String> uriClosure = computeUriClosure(uri); for (String c : uriClosure) { List<Node> nodesOfSameUri = this.uriToNodesMap.get(c); if (nodesOfSameUri == null || nodesOfSameUri.size() == 0) { // the internal node is not added to the graph before Node nn = new InternalNode(nodeIdFactory.getNodeId(c), ontologyManager.getUriLabel(c)); if (addSingleNode(nn)) newAddedNodes.add(nn); } } logger.debug("exit>"); } @SuppressWarnings("unused") private void updateLinks() { logger.debug("<enter"); List<Node> nodes = this.typeToNodesMap.get(NodeType.InternalNode); logger.debug("number of vertices: " + nodes.size()); HashSet<String> objectPropertiesDirect; HashSet<String> objectPropertiesIndirect; HashSet<String> objectPropertiesWithOnlyDomain; HashSet<String> objectPropertiesWithOnlyRange; Node source; Node target; String sourceUri; String targetUri; String id = null; Label label = null; String key; // System.out.println("size:" + nodes.size() * nodes.size()); // int count = 0; logger.debug("Number of nodes in the graph: " + nodes.size()); for (Node n1 : nodes) { for (Node n2 : nodes) { // System.out.println(count); // count++; if (n1.equals(n2)) continue; if (this.visitedSourceTargetPairs.contains(n1.getId() + n2.getId())) continue; this.visitedSourceTargetPairs.add(n1.getId() + n2.getId()); // System.out.println(n1.getId() + " --- " + n2.getId()); source = n1; target = n2; sourceUri = source.getLabel().getUri(); targetUri = target.getLabel().getUri(); // create a link from the domain to the range objectPropertiesDirect = ontologyManager.getObjectPropertiesDirect(sourceUri, targetUri); if (objectPropertiesDirect != null) for (String uri : objectPropertiesDirect) { key = source.getId() + target.getId() + uri; // check to see if the link is duplicate or not if (sourceToTargetLinkUris.contains(key)) continue; id = LinkIdFactory.getLinkId(uri, source.getId(), target.getId()); label = ontologyManager.getUriLabel(uri); Link link = new ObjectPropertyLink(id, label); link.setPriorityType(LinkPriorityType.DirectObjectProperty); addLink(source, target, link); } // create a link from the domain and all its subclasses of ObjectProperties to range and all its subclasses objectPropertiesIndirect = ontologyManager.getObjectPropertiesIndirect(sourceUri, targetUri); if (objectPropertiesIndirect != null) for (String uri : objectPropertiesIndirect) { key = source.getId() + target.getId() + uri; // check to see if the link is duplicate or not if (sourceToTargetLinkUris.contains(key)) continue; id = LinkIdFactory.getLinkId(uri, source.getId(), target.getId()); label = ontologyManager.getUriLabel(uri); Link link = new ObjectPropertyLink(id, label); // prefer the links that are actually defined between source and target in the ontology // over inherited ones. link.setPriorityType(LinkPriorityType.IndirectObjectProperty); addLink(source, target, link); } objectPropertiesWithOnlyDomain = ontologyManager.getObjectPropertiesWithOnlyDomain(sourceUri, targetUri); if (objectPropertiesWithOnlyDomain != null) for (String uri : objectPropertiesWithOnlyDomain) { key = source.getId() + target.getId() + uri; // check to see if the link is duplicate or not if (sourceToTargetLinkUris.contains(key)) continue; id = LinkIdFactory.getLinkId(uri, source.getId(), target.getId()); label = ontologyManager.getUriLabel(uri); Link link = new ObjectPropertyLink(id, label); // prefer the links that are actually defined between source and target in the ontology // over inherited ones. link.setPriorityType(LinkPriorityType.ObjectPropertyWithOnlyDomain); addLink(source, target, link); } objectPropertiesWithOnlyRange = ontologyManager.getObjectPropertiesWithOnlyRange(sourceUri, targetUri); if (objectPropertiesWithOnlyRange != null) for (String uri : objectPropertiesWithOnlyRange) { key = source.getId() + target.getId() + uri; // check to see if the link is duplicate or not if (sourceToTargetLinkUris.contains(key)) continue; id = LinkIdFactory.getLinkId(uri, source.getId(), target.getId()); label = ontologyManager.getUriLabel(uri); Link link = new ObjectPropertyLink(id, label); // prefer the links that are actually defined between source and target in the ontology // over inherited ones. link.setPriorityType(LinkPriorityType.ObjectPropertyWithOnlyRange); addLink(source, target, link); } // Add subclass links between internal nodes if (ontologyManager.isSubClass(sourceUri, targetUri, false)) { // target is subclass of source key = source.getId() + target.getId() + SubClassLink.getFixedLabel().getUri(); // check to see if the link is duplicate or not if (sourceToTargetLinkUris.contains(key)) continue; id = LinkIdFactory.getLinkId(SubClassLink.getFixedLabel().getUri(), source.getId(), target.getId()); SubClassLink subClassOfLink = new SubClassLink(id); addLink(source, target, subClassOfLink); } } } logger.debug("exit>"); } private void updateLinks2() { logger.debug("<enter"); List<Node> nodes = this.typeToNodesMap.get(NodeType.InternalNode); logger.debug("number of internal nodes: " + nodes.size()); Node source; Node target; String sourceUri; String targetUri; String id = null; // int count = 0; // System.out.println("size:" + nodes.size() * nodes.size()); for (int i = 0; i < nodes.size(); i++) { Node n1 = nodes.get(i); for (int j = i+1; j < nodes.size(); j++) { Node n2 = nodes.get(j); // System.out.println(count); // count++; if (n1.equals(n2)) continue; if (this.visitedSourceTargetPairs.contains(n1.getId() + n2.getId())) continue; if (this.visitedSourceTargetPairs.contains(n2.getId() + n1.getId())) continue; this.visitedSourceTargetPairs.add(n1.getId() + n2.getId()); source = n1; target = n2; sourceUri = source.getLabel().getUri(); targetUri = target.getLabel().getUri(); // if ((sourceUri.contains("Person") && targetUri.contains("CulturalHeritage")) || // (sourceUri.contains("CulturalHeritage") && targetUri.contains("Person"))) // System.out.println("debug1"); // if ((sourceUri.contains("E42") && targetUri.contains("E54")) || // (sourceUri.contains("E54") && targetUri.contains("E42"))) // System.out.println("debug1"); // // if ((sourceUri.contains("E22") && targetUri.contains("E54")) || // (sourceUri.contains("E54") && targetUri.contains("E22"))) // System.out.println("debug2"); // if (sourceUri.endsWith("Vehicle") && targetUri.endsWith("Observation") || // targetUri.endsWith("Vehicle") && sourceUri.endsWith("Observation")) // System.out.println("debug"); id = LinkIdFactory.getLinkId(SimpleLink.getFixedLabel().getUri(), source.getId(), target.getId()); Link link = new SimpleLink(id, SimpleLink.getFixedLabel()); // order of adding the links is based on the ascending sort of their weight value if (this.ontologyManager.isConnectedByDirectProperty(sourceUri, targetUri) || this.ontologyManager.isConnectedByDirectProperty(targetUri, sourceUri)) { logger.debug( sourceUri + " and " + targetUri + " are connected by a direct object property."); link.setPriorityType(LinkPriorityType.DirectObjectProperty); addLink(source, target, link); } else if (this.ontologyManager.isConnectedByIndirectProperty(sourceUri, targetUri) || this.ontologyManager.isConnectedByIndirectProperty(targetUri, sourceUri)) { logger.debug( sourceUri + " and " + targetUri + " are connected by an indirect object property."); link.setPriorityType(LinkPriorityType.IndirectObjectProperty); addLink(source, target, link); } else if (this.ontologyManager.isConnectedByDomainlessProperty(sourceUri, targetUri) || this.ontologyManager.isConnectedByDomainlessProperty(targetUri, sourceUri)) { logger.debug( sourceUri + " and " + targetUri + " are connected by an object property whose range is " + sourceUri + " or " + targetUri); link.setPriorityType(LinkPriorityType.ObjectPropertyWithOnlyRange); addLink(source, target, link); } else if (this.ontologyManager.isConnectedByRangelessProperty(sourceUri, targetUri) || this.ontologyManager.isConnectedByRangelessProperty(targetUri, sourceUri)) { logger.debug( sourceUri + " and " + targetUri + " are connected by an object property whose domain is " + sourceUri + " or " + targetUri); link.setPriorityType(LinkPriorityType.ObjectPropertyWithOnlyDomain); addLink(source, target, link); } else if (this.ontologyManager.isSubClass(sourceUri, targetUri, false) || this.ontologyManager.isSubClass(targetUri, sourceUri, false)) { logger.debug( sourceUri + " and " + targetUri + " are connected by a subClassOf relation."); link.setPriorityType(LinkPriorityType.SubClassOf); addLink(source, target, link); } else if (this.ontologyManager.isConnectedByDomainlessAndRangelessProperty(sourceUri, targetUri)) {// || // this.ontologyManager.isConnectedByDomainlessAndRangelessProperty(targetUri, sourceUri)) { link.setPriorityType(LinkPriorityType.ObjectPropertyWithoutDomainAndRange); addLink(source, target, link); } } } logger.debug("exit>"); } public HashMap<String, LinkPriorityType> getPossibleUris(String sourceUri, String targetUri) { HashMap<String, LinkPriorityType> linkUris = new HashMap<String, LinkPriorityType>(); HashSet<String> objectPropertiesDirect; HashSet<String> objectPropertiesIndirect; HashSet<String> objectPropertiesWithOnlyDomain; HashSet<String> objectPropertiesWithOnlyRange; HashMap<String, Label> objectPropertiesWithoutDomainAndRange = ontologyManager.getObjectPropertiesWithoutDomainAndRange(); // if (targetUri.endsWith("Person") && sourceUri.endsWith("Organisation")) // System.out.println("debug"); // if (sourceUri.endsWith("Vehicle") && targetUri.endsWith("Observation") || // targetUri.endsWith("Vehicle") && sourceUri.endsWith("Observation")) // System.out.println("debug"); objectPropertiesDirect = ontologyManager.getObjectPropertiesDirect(sourceUri, targetUri); if (objectPropertiesDirect != null) { for (String s : objectPropertiesDirect) linkUris.put(s, LinkPriorityType.DirectObjectProperty); } objectPropertiesIndirect = ontologyManager.getObjectPropertiesIndirect(sourceUri, targetUri); if (objectPropertiesIndirect != null) { for (String s : objectPropertiesIndirect) linkUris.put(s, LinkPriorityType.IndirectObjectProperty); } objectPropertiesWithOnlyDomain = ontologyManager.getObjectPropertiesWithOnlyDomain(sourceUri, targetUri); if (objectPropertiesWithOnlyDomain != null) { for (String s : objectPropertiesWithOnlyDomain) linkUris.put(s, LinkPriorityType.ObjectPropertyWithOnlyDomain); } objectPropertiesWithOnlyRange = ontologyManager.getObjectPropertiesWithOnlyRange(sourceUri, targetUri); if (objectPropertiesWithOnlyRange != null) { for (String s : objectPropertiesWithOnlyRange) linkUris.put(s, LinkPriorityType.ObjectPropertyWithOnlyRange); } if (ontologyManager.isSubClass(sourceUri, targetUri, true)) linkUris.put(Uris.RDFS_SUBCLASS_URI, LinkPriorityType.SubClassOf); if (objectPropertiesWithoutDomainAndRange != null) { for (String s : objectPropertiesWithoutDomainAndRange.keySet()) linkUris.put(s, LinkPriorityType.ObjectPropertyWithoutDomainAndRange); } return linkUris; } public List<Link> getPossibleLinks(String sourceId, String targetId) { List<Link> sortedLinks = new ArrayList<Link>(); Node source = this.idToNodeMap.get(sourceId); Node target = this.idToNodeMap.get(targetId); if (source == null || target == null) { logger.debug("Cannot find source or target in the graph."); return sortedLinks; } if (source instanceof ColumnNode || target instanceof ColumnNode) { logger.debug("Source or target is a column node."); return sortedLinks; } String sourceUri, targetUri; sourceUri = source.getLabel().getUri(); targetUri = target.getLabel().getUri(); HashMap<String, LinkPriorityType> links = this.getPossibleUris(sourceUri, targetUri); String id; Label label; String uri; for (Entry<String, LinkPriorityType> entry : links.entrySet()) { uri = entry.getKey(); id = LinkIdFactory.getLinkId(uri, sourceId, targetId); label = new Label(ontologyManager.getUriLabel(uri)); Link newLink; if (uri.equalsIgnoreCase(Uris.RDFS_SUBCLASS_URI)) newLink = new SubClassLink(id); else newLink = new ObjectPropertyLink(id, label); newLink.setPriorityType(entry.getValue()); sortedLinks.add(newLink); } return sortedLinks; } // public void serialize(String fileName) throws IOException { // // /** // * Kryo // */ // // // Kryo: problem with classes that do not have zero-arg constructors // Kryo kryo = new Kryo(); // JavaSerializer javaSerializer = new JavaSerializer(); // kryo.register(DirectedWeightedMultigraph.class, javaSerializer); // kryo.register(Node.class, javaSerializer); // kryo.register(InternalNode.class, javaSerializer); // kryo.register(ColumnNode.class, javaSerializer); // kryo.register(DataPropertyLink.class, javaSerializer); // kryo.register(ObjectPropertyLink.class, javaSerializer); // Output output = new Output(new FileOutputStream(fileName)); // kryo.writeObject(output, this); // output.close(); // // /** // * Protostuff // */ // // Schema<GraphBuilder> schema = RuntimeSchema.getSchema(GraphBuilder.class); // FileOutputStream f = new FileOutputStream(fileName); // ObjectOutputStream out = new ObjectOutputStream(f); // LinkedBuffer buffer = LinkedBuffer.allocate(512); // try // { //// int totalBytes = ProtobufIOUtil.writeTo(out, this, schema, buffer); // ProtobufIOUtil.writeTo(out, this, schema, buffer); // } // finally // { // buffer.clear(); // } // // /** // * Gson // */ // // Gson gson = new Gson(); // FileOutputStream f = new FileOutputStream(fileName); // ObjectOutputStream out = new ObjectOutputStream(f); // JsonWriter writer = new JsonWriter(new OutputStreamWriter(out)); // writer.setIndent(" "); // writer.beginArray(); // gson.toJson(this, GraphBuilder.class, writer); // writer.endArray(); // writer.close(); // // Kryo kryo = new Kryo(); // kryo.register(GraphBuilder.class, new Serializer<GraphBuilder>() { // // public void write (Kryo kryo, Output output, GraphBuilder object) { // output.getOutputStream().w.writeInt(object.); // output.writeInt(object.y); // kryo.writeClassAndObject(output, object); // } // // public GraphBuilder read (Kryo kryo, Input input, Class<GraphBuilder> type) { // Tile tile = new Tile(); // kryo.reference(tile); // Only necessary if Kryo#setReferences is true AND Tile#something could reference this tile. // tile.x = input.readInt(); // tile.y = input..readInt(); // tile.something = kryo.readClassAndObject(input); // return tile; // } // } // // class MyNullKeySerializer extends JsonSerializer<Object> // { // @Override // public void serialize(Object nullKey, JsonGenerator jsonGenerator, SerializerProvider unused) // throws IOException, JsonProcessingException // { // jsonGenerator.writeFieldName(""); // } // } // // FileOutputStream f = new FileOutputStream(fileName); // ObjectOutputStream out = new ObjectOutputStream(f); // ObjectMapper mapper = new ObjectMapper(); //// mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY); // mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false); // mapper.setSerializationInclusion(Include.NON_NULL); // mapper.getSerializerProvider().setNullKeySerializer(new MyNullKeySerializer()); // mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); // mapper.writeValue(out, this); // // } // public static GraphBuilder deserialize(String fileName) throws IOException { // // /** // * Kryo // */ // // Kryo kryo = new KryoReflectionFactorySupport(); // JavaSerializer javaSerializer = new JavaSerializer(); // kryo.register(DirectedWeightedMultigraph.class, javaSerializer); // kryo.register(InternalNode.class, javaSerializer); // kryo.register(ColumnNode.class, javaSerializer); // kryo.register(DataPropertyLink.class, javaSerializer); // kryo.register(ObjectPropertyLink.class, javaSerializer); // Input input = new Input(new FileInputStream(fileName)); // GraphBuilder graphBuilder = kryo.readObject(input, GraphBuilder.class); // input.close(); // return graphBuilder; // // /** // * Protostuff // */ // // Schema<GraphBuilder> schema = RuntimeSchema.getSchema(GraphBuilder.class); // FileInputStream f = new FileInputStream(fileName); // ObjectInputStream in = new ObjectInputStream(f); // LinkedBuffer buffer = LinkedBuffer.allocate(512); // // GraphBuilder g = new GraphBuilder(); // ProtobufIOUtil.mergeFrom(in, g, schema, buffer); // return g; // // /** // * Gson // */ // // Gson gson = new Gson(); // FileInputStream f = new FileInputStream(fileName); // ObjectInputStream in = new ObjectInputStream(f); // JsonReader reader = new JsonReader(new InputStreamReader(in)); // reader.beginArray(); // GraphBuilder graphBuilder = gson.fromJson(reader, GraphBuilder.class); // reader.endArray(); // reader.close(); // return graphBuilder; // // FileInputStream f = new FileInputStream(fileName); // ObjectInputStream in = new ObjectInputStream(f); // ObjectMapper mapper = new ObjectMapper(); // GraphBuilder graphBuilder = mapper.readValue(in, GraphBuilder.class); // return graphBuilder; // // } public static void main(String[] args) throws Exception { System.out.println(Integer.class.getFields()[0].getName()); /** Check if any ontology needs to be preloaded **/ String preloadedOntDir = "/Users/mohsen/Documents/Academic/ISI/_GIT/Web-Karma/preloaded-ontologies/"; File ontDir = new File(preloadedOntDir); if (ontDir.exists()) { File[] ontologies = ontDir.listFiles(); OntologyManager mgr = new OntologyManager(); for (File ontology: ontologies) { if (ontology.getName().endsWith(".owl") || ontology.getName().endsWith(".rdf")) { logger.info("Loading ontology file: " + ontology.getAbsolutePath()); try { mgr.doImport(ontology); } catch (Exception t) { logger.error ("Error loading ontology: " + ontology.getAbsolutePath(), t); } } } // update the cache at the end when all files are added to the model mgr.updateCache(); } else { logger.info("No directory for preloading ontologies exists."); } DirectedWeightedMultigraph<Node, Link> g = new DirectedWeightedMultigraph<Node, Link>(Link.class); Node n1 = new ColumnNode("n1", "h1", "B", ""); Node n2 = new InternalNode("n2", null); Link l1 = new DataPropertyLink("e1", null); g.addVertex(n1); g.addVertex(n2); g.addEdge(n1, n2, l1); GraphUtil.printGraph(g); // GraphUtil.serialize(g, "test"); // DirectedWeightedMultigraph<Node, Link> gprime = GraphUtil.deserialize("test"); // // GraphUtil.printGraph(gprime); // g.removeEdge(l1); // GraphUtil.printGraph(g); // g.removeVertex(n2); // GraphUtil.printGraph(g); } }