Github user jessehatfield commented on a diff in the pull request: https://github.com/apache/incubator-rya/pull/206#discussion_r134081316 --- Diff: sail/src/main/java/org/apache/rya/rdftriplestore/inference/InferenceEngine.java --- @@ -416,22 +425,131 @@ private void refreshHasValueRestrictions(Map<Resource, URI> restrictions) throws } } - private static Vertex getVertex(Graph graph, Object id) { - Iterator<Vertex> it = graph.vertices(id.toString()); + private void refreshIntersectionOf() throws QueryEvaluationException { + final Map<Resource, List<Set<Resource>>> intersectionsProp = new HashMap<>(); + + // First query for all the owl:intersectionOf's. + // If we have the following intersectionOf: + // :A owl:intersectionOf[:B, :C] + // It will be represented by triples following a pattern similar to: + // <:A> owl:intersectionOf _:bnode1 . + // _:bnode1 rdf:first <:B> . + // _:bnode1 rdf:rest _:bnode2 . + // _:bnode2 rdf:first <:C> . + // _:bnode2 rdf:rest rdf:nil . + ryaDaoQueryWrapper.queryAll(null, OWL.INTERSECTIONOF, null, new RyaDaoStatementIterHandler() { + @Override + public void handleStatementIter(final Statement st1) throws Exception { + final Resource type = st1.getSubject(); + // head will point to a type that is part of the intersection. + URI head = (URI) st1.getObject(); + if (!intersectionsProp.containsKey(type)) { + intersectionsProp.put(type, new ArrayList<Set<Resource>>()); + } + final Set<Resource> intersection = new HashSet<>(); + // Go through and find all bnodes that are part of the defined + // intersection. + while (!RDF.NIL.equals(head)) { + // rdf.first will point to a type item that is in the + // intersection. + ryaDaoQueryWrapper.queryFirst(head, RDF.FIRST, null, new RyaDaoStatementIterHandler() { + @Override + public void handleStatementIter(final Statement st2) throws Exception{ + // The object found in the query represents a type + // that should be included in the intersection. + final URI obj2 = (URI) st2.getObject(); + intersection.add(obj2); + } + }); + final List<URI> headHolder = new ArrayList<>(1); + // rdf.rest will point to the next bnode that's part of the + // intersection. + ryaDaoQueryWrapper.queryFirst(head, RDF.REST, null, new RyaDaoStatementIterHandler() { + @Override + public void handleStatementIter(final Statement st3) throws Exception { + // This object is the next bnode head to look for. + final URI obj3 = (URI) st3.getObject(); + headHolder.add(obj3); + } + }); + // As long as we get a new head there are more bnodes that + // are part of the intersection. Keep going until we reach + // rdf.nil. + if (!headHolder.isEmpty()) { + head = headHolder.get(0); + } else { + head = RDF.NIL; + } + } + // Add this intersection for this type. There may be more + // intersections for this type so each type has a list of + // intersection sets. + intersectionsProp.get(type).add(intersection); + } + }); + + for (final Map.Entry<Resource, List<Set<Resource>>> entry : intersectionsProp.entrySet()) { + final Resource type = entry.getKey(); + final List<Set<Resource>> intersectionList = entry.getValue(); + final Set<Resource> otherTypes = new HashSet<>(); + // Combine all of a type's intersections together. + for (final Set<Resource> intersection : intersectionList) { + otherTypes.addAll(intersection); + } + for (final Resource other : otherTypes) { + // :A intersectionOf[:B, :C] implies that + // :A subclassOf :B + // :A subclassOf :C + // So add each type that's part of the intersection to the + // subClassOf graph. + addSubClassOf(type, other); + for (final Set<Resource> intersection : intersectionList) { + if (!intersection.contains(other)) { + addIntersection(intersection, other); --- End diff -- I'm not sure if that's the same. I can read "A = (B and C)" two ways -- either "A is the intersection of B and C": <A> owl:intersectionOf (<B> <C>) . <D> owl:intersectionOf (<B> <C>) . <D> rdfs:subClassOf <E> . or "A is equivalent to some anonymous class which is the intersection of B and C: <A> owl:equivalentClass _:bnode _:bnode owl:intersectionOf (<B> <C>) . _:bnode owl:equivalentClass <D> . <D> rdfs:subClassOf <E> . In the latter case, we have A subClassOf E just from subclass and equivalent class transitivity, without touching the intersection. In the former, I suppose you could infer that A and D are equivalent classes by comparing their intersections. That would require comparing the actual contents of all intersection lists to find any pairs that contain the same set of classes. That might be something to do in the future, but I don't think I'd try to do it at this point since we're not making that kind of check with any of the other class expressions (unions, property restrictions, etc).
--- If your project is set up for it, you can reply to this email and have your reply appear on GitHub as well. If your project does not have this feature enabled and wishes so, or if the feature is enabled but not working, please contact infrastructure at infrastruct...@apache.org or file a JIRA ticket with INFRA. ---