Skip to content

Commit

Permalink
apacheGH-2673: [ontapi] OntDisjoints - require more than one member (…
Browse files Browse the repository at this point in the history
…for EL, QL, RL)
  • Loading branch information
sszuev authored and afs committed Sep 10, 2024
1 parent 7aa1474 commit 73699fc
Show file tree
Hide file tree
Showing 8 changed files with 254 additions and 112 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,8 @@ public class OntPersonalities {
.add(OntNegativeAssertion.class, OWL2ObjectFactories.ANY_NEGATIVE_PROPERTY_ASSERTION)

// disjoint anonymous collections:
.add(OntDisjoint.Classes.class, OWL2ObjectFactories.CLASSES_DISJOINT)
.add(OntDisjoint.Individuals.class, OWL2ObjectFactories.DIFFERENT_INDIVIDUALS_DISJOINT)
.add(OntDisjoint.Classes.class, OWL2ObjectFactories.EL_CLASSES_DISJOINT)
.add(OntDisjoint.Individuals.class, OWL2ObjectFactories.EL_QL_RL_DIFFERENT_INDIVIDUALS_DISJOINT)
.add(OntDisjoint.class, OWL2ObjectFactories.EL_ANY_DISJOINT);

/**
Expand Down Expand Up @@ -370,10 +370,10 @@ public class OntPersonalities {
.add(OntDataRange.class, OWL2ObjectFactories.QL_ANY_DATARANGE)

// disjoint anonymous collections:
.add(OntDisjoint.Classes.class, OWL2ObjectFactories.QL_CLASSES_DISJOINT)
.add(OntDisjoint.Individuals.class, OWL2ObjectFactories.DIFFERENT_INDIVIDUALS_DISJOINT)
.add(OntDisjoint.ObjectProperties.class, OWL2ObjectFactories.OBJECT_PROPERTIES_DISJOINT)
.add(OntDisjoint.DataProperties.class, OWL2ObjectFactories.DATA_PROPERTIES_DISJOINT)
.add(OntDisjoint.Classes.class, OWL2ObjectFactories.QL_RL_CLASSES_DISJOINT)
.add(OntDisjoint.Individuals.class, OWL2ObjectFactories.EL_QL_RL_DIFFERENT_INDIVIDUALS_DISJOINT)
.add(OntDisjoint.ObjectProperties.class, OWL2ObjectFactories.QL_RL_OBJECT_PROPERTIES_DISJOINT)
.add(OntDisjoint.DataProperties.class, OWL2ObjectFactories.QL_RL_DATA_PROPERTIES_DISJOINT)
.add(OntDisjoint.Properties.class, OWL2ObjectFactories.ANY_PROPERTIES_DISJOINT)
.add(OntDisjoint.class, OWL2ObjectFactories.ANY_DISJOINT);

Expand Down Expand Up @@ -445,10 +445,10 @@ public class OntPersonalities {
.add(OntNegativeAssertion.class, OWL2ObjectFactories.ANY_NEGATIVE_PROPERTY_ASSERTION)

// disjoint anonymous collections:
.add(OntDisjoint.Classes.class, OWL2ObjectFactories.RL_CLASSES_DISJOINT)
.add(OntDisjoint.Individuals.class, OWL2ObjectFactories.DIFFERENT_INDIVIDUALS_DISJOINT)
.add(OntDisjoint.ObjectProperties.class, OWL2ObjectFactories.OBJECT_PROPERTIES_DISJOINT)
.add(OntDisjoint.DataProperties.class, OWL2ObjectFactories.DATA_PROPERTIES_DISJOINT)
.add(OntDisjoint.Classes.class, OWL2ObjectFactories.QL_RL_CLASSES_DISJOINT)
.add(OntDisjoint.Individuals.class, OWL2ObjectFactories.EL_QL_RL_DIFFERENT_INDIVIDUALS_DISJOINT)
.add(OntDisjoint.ObjectProperties.class, OWL2ObjectFactories.QL_RL_OBJECT_PROPERTIES_DISJOINT)
.add(OntDisjoint.DataProperties.class, OWL2ObjectFactories.QL_RL_DATA_PROPERTIES_DISJOINT)
.add(OntDisjoint.Properties.class, OWL2ObjectFactories.ANY_PROPERTIES_DISJOINT)
.add(OntDisjoint.class, OWL2ObjectFactories.ANY_DISJOINT);
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -967,25 +967,33 @@ public OntGraphModelImpl deleteOntList(OntObject subject, Property predicate, On
public OntDisjoint.Classes createDisjointClasses(Collection<OntClass> classes) {
checkType(OntDisjoint.Classes.class);
checkType(OntClass.IntersectionOf.class);
return checkCreate(model -> OntDisjointImpl.createDisjointClasses(this, classes.stream()), OntDisjoint.Classes.class);
return checkCreate(model ->
OntDisjointImpl.createDisjointClasses(model, classes.stream()), OntDisjoint.Classes.class
);
}

@Override
public OntDisjoint.Individuals createDifferentIndividuals(Collection<OntIndividual> individuals) {
checkType(OntDisjoint.Individuals.class);
return OntDisjointImpl.createDifferentIndividuals(this, individuals.stream());
return checkCreate(model ->
OntDisjointImpl.createDifferentIndividuals(model, individuals.stream()), OntDisjoint.Individuals.class
);
}

@Override
public OntDisjoint.ObjectProperties createDisjointObjectProperties(Collection<OntObjectProperty> properties) {
checkType(OntDisjoint.ObjectProperties.class);
return OntDisjointImpl.createDisjointObjectProperties(this, properties.stream());
return checkCreate(model ->
OntDisjointImpl.createDisjointObjectProperties(model, properties.stream()), OntDisjoint.ObjectProperties.class
);
}

@Override
public OntDisjoint.DataProperties createDisjointDataProperties(Collection<OntDataProperty> properties) {
checkType(OntDisjoint.DataProperties.class);
return OntDisjointImpl.createDisjointDataProperties(this, properties.stream());
return checkCreate(model ->
OntDisjointImpl.createDisjointDataProperties(model, properties.stream()), OntDisjoint.DataProperties.class
);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ public class OWL1ObjectFactories {
);

public static final Function<OntConfig, EnhNodeFactory> DIFFERENT_INDIVIDUALS_DISJOINT =
OntDisjoints::createDifferentIndividualsFactory;
OntDisjoints::createDLFullDifferentIndividualsFactory;
public static final Function<OntConfig, EnhNodeFactory> ANY_DISJOINT = DIFFERENT_INDIVIDUALS_DISJOINT;

private static boolean isNamedIndividual(Node n, EnhGraph eg) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,18 @@
import org.apache.jena.ontapi.impl.objects.OntAnnotationImpl;
import org.apache.jena.ontapi.impl.objects.OntClassImpl;
import org.apache.jena.ontapi.impl.objects.OntDataRangeImpl;
import org.apache.jena.ontapi.impl.objects.OntDisjointImpl;
import org.apache.jena.ontapi.impl.objects.OntFacetRestrictionImpl;
import org.apache.jena.ontapi.impl.objects.OntIDImpl;
import org.apache.jena.ontapi.impl.objects.OntIndividualImpl;
import org.apache.jena.ontapi.impl.objects.OntNegativePropertyAssertionImpl;
import org.apache.jena.ontapi.impl.objects.OntObjectImpl;
import org.apache.jena.ontapi.impl.objects.OntSimpleClassImpl;
import org.apache.jena.ontapi.model.OntClass;
import org.apache.jena.ontapi.model.OntDataProperty;
import org.apache.jena.ontapi.model.OntDataRange;
import org.apache.jena.ontapi.model.OntDisjoint;
import org.apache.jena.ontapi.model.OntFacetRestriction;
import org.apache.jena.ontapi.model.OntIndividual;
import org.apache.jena.ontapi.model.OntNegativeAssertion;
import org.apache.jena.ontapi.model.OntObjectProperty;
import org.apache.jena.rdf.model.RDFList;
import org.apache.jena.vocabulary.OWL2;
import org.apache.jena.vocabulary.RDF;
Expand Down Expand Up @@ -788,34 +785,18 @@ public final class OWL2ObjectFactories {
OntFacetRestriction.LangRange.class
);

public static final EnhNodeFactory CLASSES_DISJOINT = OntDisjoints.createFactory(
OntDisjointImpl.ClassesImpl.class,
OntDisjointImpl.ClassesImpl::new,
OWL2.AllDisjointClasses,
OntClass.class,
true,
OWL2.members
);
public static final EnhNodeFactory QL_CLASSES_DISJOINT = OntDisjoints.createQLRLOntDisjointFactory();
public static final EnhNodeFactory RL_CLASSES_DISJOINT = OntDisjoints.createQLRLOntDisjointFactory();
public static final EnhNodeFactory CLASSES_DISJOINT = OntDisjoints.createDisjointClassesFactory(0);
public static final EnhNodeFactory EL_CLASSES_DISJOINT = OntDisjoints.createDisjointClassesFactory(2);
public static final EnhNodeFactory QL_RL_CLASSES_DISJOINT = OntDisjoints.createQLRLDisjointClassesFactory();
public static final Function<OntConfig, EnhNodeFactory> DIFFERENT_INDIVIDUALS_DISJOINT =
OntDisjoints::createDifferentIndividualsFactory;
public static final EnhNodeFactory OBJECT_PROPERTIES_DISJOINT = OntDisjoints.createFactory(
OntDisjointImpl.ObjectPropertiesImpl.class,
OntDisjointImpl.ObjectPropertiesImpl::new,
OWL2.AllDisjointProperties,
OntObjectProperty.class,
false,
OWL2.members
);
public static final EnhNodeFactory DATA_PROPERTIES_DISJOINT = OntDisjoints.createFactory(
OntDisjointImpl.DataPropertiesImpl.class,
OntDisjointImpl.DataPropertiesImpl::new,
OWL2.AllDisjointProperties,
OntDataProperty.class,
false,
OWL2.members
);
OntDisjoints::createDLFullDifferentIndividualsFactory;
public static final EnhNodeFactory EL_QL_RL_DIFFERENT_INDIVIDUALS_DISJOINT =
OntDisjoints.createELQLRLDifferentIndividualsFactory();
public static final EnhNodeFactory OBJECT_PROPERTIES_DISJOINT = OntDisjoints.createDisjointObjectPropertiesFactory(0);
public static final EnhNodeFactory QL_RL_OBJECT_PROPERTIES_DISJOINT = OntDisjoints.createDisjointObjectPropertiesFactory(2);
public static final EnhNodeFactory DATA_PROPERTIES_DISJOINT = OntDisjoints.createDisjointDataPropertiesFactory(0);
public static final EnhNodeFactory QL_RL_DATA_PROPERTIES_DISJOINT = OntDisjoints.createDisjointDataPropertiesFactory(2);

public static final EnhNodeFactory ANY_PROPERTIES_DISJOINT = OntEnhNodeFactories.createFrom(
OntDisjoints.PROPERTIES_FINDER,
OntDisjoint.ObjectProperties.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import org.apache.jena.enhanced.EnhGraph;
import org.apache.jena.enhanced.EnhNode;
import org.apache.jena.graph.Graph;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.Triple;
import org.apache.jena.ontapi.OntModelControls;
Expand All @@ -33,7 +32,9 @@
import org.apache.jena.ontapi.common.OntEnhNodeFactories;
import org.apache.jena.ontapi.impl.objects.OntDisjointImpl;
import org.apache.jena.ontapi.model.OntClass;
import org.apache.jena.ontapi.model.OntDataProperty;
import org.apache.jena.ontapi.model.OntIndividual;
import org.apache.jena.ontapi.model.OntObjectProperty;
import org.apache.jena.ontapi.utils.Iterators;
import org.apache.jena.rdf.model.Property;
import org.apache.jena.rdf.model.RDFList;
Expand All @@ -43,13 +44,14 @@
import org.apache.jena.vocabulary.OWL2;

import java.util.function.BiFunction;
import java.util.function.Predicate;

final class OntDisjoints {
public static final EnhNodeFinder PROPERTIES_FINDER = new EnhNodeFinder.ByType(OWL2.AllDisjointProperties);
public static final EnhNodeFinder DISJOINT_FINDER = OntEnhNodeFactories.createFinder(OWL2.AllDisjointClasses,
OWL2.AllDifferent, OWL2.AllDisjointProperties);

public static EnhNodeFactory createDifferentIndividualsFactory(OntConfig config) {
public static EnhNodeFactory createDLFullDifferentIndividualsFactory(OntConfig config) {
boolean useDistinctMembers = config.getBoolean(OntModelControls.USE_OWL1_DISTINCT_MEMBERS_PREDICATE_FEATURE);
boolean compatible = config.getBoolean(OntModelControls.USE_OWL2_DEPRECATED_VOCABULARY_FEATURE);
Property[] predicates;
Expand All @@ -65,48 +67,106 @@ public static EnhNodeFactory createDifferentIndividualsFactory(OntConfig config)
(n, g) -> new OntDisjointImpl.IndividualsImpl(n, g, !compatible, useDistinctMembers),
OWL2.AllDifferent,
OntIndividual.class,
true,
it -> true,
0,
predicates
);
}

public static EnhNodeFactory createFactory(
Class<? extends OntDisjointImpl<?>> impl,
BiFunction<Node, EnhGraph, EnhNode> producer,
Resource type,
Class<? extends RDFNode> view,
boolean allowEmptyList,
Property... predicates) {
EnhNodeProducer maker = new EnhNodeProducer.WithType(impl, type, producer);
EnhNodeFinder finder = new EnhNodeFinder.ByType(type);
EnhNodeFilter filter = EnhNodeFilter.ANON.and(new EnhNodeFilter.HasType(type));
return OntEnhNodeFactories.createCommon(maker, finder, filter
.and(getHasPredicatesFilter(predicates))
.and(getHasMembersOfFilter(view, allowEmptyList, predicates)));
public static EnhNodeFactory createELQLRLDifferentIndividualsFactory() {
return createFactory(
OntDisjointImpl.IndividualsImpl.class,
(n, g) -> new OntDisjointImpl.IndividualsImpl(n, g, true, false),
OWL2.AllDifferent,
OntIndividual.class,
it -> true,
2,
OWL2.members
);
}

public static EnhNodeFactory createDisjointObjectPropertiesFactory(int atLeastN) {
return createFactory(
OntDisjointImpl.ObjectPropertiesImpl.class,
OntDisjointImpl.ObjectPropertiesImpl::new,
OWL2.AllDisjointProperties,
OntObjectProperty.class,
it -> true,
atLeastN,
OWL2.members
);
}

public static EnhNodeFactory createDisjointDataPropertiesFactory(int atLeastN) {
return createFactory(
OntDisjointImpl.DataPropertiesImpl.class,
OntDisjointImpl.DataPropertiesImpl::new,
OWL2.AllDisjointProperties,
OntDataProperty.class,
it -> true,
atLeastN,
OWL2.members
);
}

public static EnhNodeFactory createDisjointClassesFactory(int atLeastN) {
return createFactory(
OntDisjointImpl.QLRLClassesImpl.class,
OntDisjointImpl.QLRLClassesImpl::new,
OWL2.AllDisjointClasses,
OntClass.class,
it -> true,
atLeastN,
OWL2.members
);
}

public static EnhNodeFactory createQLRLOntDisjointFactory() {
EnhNodeProducer maker = new EnhNodeProducer.WithType(
public static EnhNodeFactory createQLRLDisjointClassesFactory() {
return createFactory(
OntDisjointImpl.QLRLClassesImpl.class,
OntDisjointImpl.QLRLClassesImpl::new,
OWL2.AllDisjointClasses,
OntDisjointImpl.QLRLClassesImpl::new
OntClass.class,
OntClass::canAsDisjointClass,
2,
OWL2.members
);
EnhNodeFinder finder = new EnhNodeFinder.ByType(OWL2.AllDisjointClasses);
EnhNodeFilter filter = EnhNodeFilter.ANON.and(new EnhNodeFilter.HasType(OWL2.AllDisjointClasses)).and((n, g) -> {
ExtendedIterator<Triple> res = g.asGraph().find(n, OWL2.members.asNode(), Node.ANY);
}

private static <X extends RDFNode> EnhNodeFactory createFactory(
Class<? extends OntDisjointImpl<?>> impl,
BiFunction<Node, EnhGraph, EnhNode> producer,
Resource rdfType,
Class<X> memberType,
Predicate<X> testMember,
int atLeastN,
Property... membersPredicates
) {
EnhNodeProducer maker = new EnhNodeProducer.WithType(impl, rdfType, producer);
EnhNodeFinder finder = new EnhNodeFinder.ByType(rdfType);
EnhNodeFilter filter = EnhNodeFilter.ANON.and(new EnhNodeFilter.HasType(rdfType)).and((n, g) -> {
ExtendedIterator<Triple> res;
if (membersPredicates.length == 1) {
res = g.asGraph().find(n, membersPredicates[0].asNode(), Node.ANY);
} else {
res = Iterators.flatMap(Iterators.of(membersPredicates), it -> g.asGraph().find(n, it.asNode(), Node.ANY));
}
try {
while (res.hasNext()) {
Node listNode = res.next().getObject();
if (!STDObjectFactories.RDF_LIST.canWrap(listNode, g)) {
return false;
}
if (atLeastN == 0) {
return true;
}
RDFList list = (RDFList) STDObjectFactories.RDF_LIST.wrap(listNode, g);
if (Iterators.hasAtLeast(
list.iterator()
.mapWith(it ->
OntEnhGraph.asPersonalityModel(g).findNodeAs(it.asNode(), OntClass.class)
OntEnhGraph.asPersonalityModel(g).findNodeAs(it.asNode(), memberType)
)
.filterKeep(it -> it != null && it.canAsDisjointClass()), 2)) {
.filterKeep(it -> it != null && testMember.test(it)), atLeastN)) {
return true;
}
}
Expand All @@ -117,46 +177,4 @@ public static EnhNodeFactory createQLRLOntDisjointFactory() {
});
return OntEnhNodeFactories.createCommon(maker, finder, filter);
}

private static EnhNodeFilter getHasPredicatesFilter(Property... predicates) {
if (predicates.length == 0) {
throw new IllegalArgumentException();
}
EnhNodeFilter res = new EnhNodeFilter.HasPredicate(predicates[0]);
for (int i = 1; i < predicates.length; i++) {
res = res.or(new EnhNodeFilter.HasPredicate(predicates[i]));
}
return res;
}

private static EnhNodeFilter getHasMembersOfFilter(Class<? extends RDFNode> view,
boolean allowEmptyList,
Property... predicates) {
return (node, eg) -> {
ExtendedIterator<Node> res = listRoots(node, eg.asGraph(), predicates);
try {
while (res.hasNext()) {
if (testList(res.next(), eg, view, allowEmptyList)) return true;
}
} finally {
res.close();
}
return false;
};
}

private static ExtendedIterator<Node> listRoots(Node node, Graph graph, Property... predicates) {
return Iterators.flatMap(Iterators.of(predicates),
p -> graph.find(node, p.asNode(), Node.ANY).mapWith(Triple::getObject));
}

private static boolean testList(Node node, EnhGraph graph, Class<? extends RDFNode> view, boolean allowEmptyList) {
if (!STDObjectFactories.RDF_LIST.canWrap(node, graph)) {
return false;
}
if (view == null) return true;
RDFList list = (RDFList) STDObjectFactories.RDF_LIST.wrap(node, graph);
return (list.isEmpty() && allowEmptyList) ||
Iterators.anyMatch(list.iterator().mapWith(RDFNode::asNode), n -> OntEnhGraph.canAs(view, n, graph));
}
}
Loading

0 comments on commit 73699fc

Please sign in to comment.