All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.jena.ontapi.model.OntIndividual Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

package org.apache.jena.ontapi.model;

import org.apache.jena.ontapi.OntJenaException;
import org.apache.jena.rdf.model.Literal;
import org.apache.jena.rdf.model.Property;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.vocabulary.OWL2;
import org.apache.jena.vocabulary.RDF;

import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;

/**
 * Interface for named and anonymous individuals.
 */
@SuppressWarnings("rawtypes")
public interface OntIndividual extends OntObject, AsNamed, HasDisjoint {

    /**
     * Removes a class assertion statement for the given class.
     * Like others methods {@code #remove..(..)} (see {@link #remove(Property, RDFNode)}),
     * this operation does nothing in case no match found
     * and in case {@code null} is specified
     * it removes all class assertion statements including all their annotations.
     * To delete the individual with its content
     * the method {@link OntModel#removeOntObject(OntObject)} can be used.
     *
     * @param clazz {@link OntClass} or {@code null} to remove all class assertions
     * @return this instance to allow cascading calls
     * @see #attachClass(OntClass)
     * @see #addClassAssertion(OntClass)
     * @see OntModel#removeOntObject(OntObject)
     */
    OntIndividual detachClass(Resource clazz);

    /**
     * Answers a {@code Stream} over the class expressions to which this individual belongs,
     * including super-classes if the flag {@code direct} is {@code false}.
     * If the flag {@code direct} is {@code true}, then only direct types are returned,
     * and the method is effectively equivalent to the method {@link #classes()}.
     * See also {@link OntClass#superClasses(boolean)}.
     *
     * @param direct if {@code true}, only answers those {@link OntClass}s that are direct types of this individual,
     *               not the superclasses of the class etc
     * @return distinct {@code Stream} of {@link OntClass class expressions}
     * @see #classes()
     * @see OntClass#superClasses(boolean)
     */
    Stream classes(boolean direct);

    /**
     * {@inheritDoc}
     * For individuals, content also includes negative property assertion statements.
     *
     * @return {@code Stream} of content {@link OntStatement}s
     */
    @Override
    Stream content();

    @Override
    default Named asNamed() {
        return as(Named.class);
    }

    /**
     * Returns all class types (direct and indirect).
     *
     * @return {@code Stream} of {@link OntClass}s
     */
    default Stream classes() {
        return classes(false);
    }

    /**
     * Answers {@code true} if the given class is in the class-type closure.
     *
     * @param clazz  {@link OntClass} to test
     * @param direct see {@link OntIndividual#classes(boolean)}
     * @return true if the specified class found
     */
    default boolean hasOntClass(OntClass clazz, boolean direct) {
        Objects.requireNonNull(clazz);
        if (!clazz.canAsAssertionClass()) {
            return false;
        }
        try (Stream classes = classes(direct)) {
            return classes.anyMatch(clazz::equals);
        }
    }

    /**
     * Answers a class to which this individual belongs,
     * If there is more than one such class, an arbitrary selection is made.
     *
     * @return {@link Optional} wrapping {@code OntClass}
     */
    default Optional ontClass() {
        try (Stream classes = objects(RDF.type, OntClass.class)) {
            return classes.findFirst();
        }
    }

    /**
     * Lists all same individuals.
     * The pattern to search for is {@code ai owl:sameAs aj}, where {@code ai} is this individual.
     *
     * @return {@code Stream} of {@link OntIndividual}s
     */
    default Stream sameIndividuals() {
        return objects(OWL2.sameAs, OntIndividual.class);
    }

    /**
     * Lists all {@code OntDisjoint} sections where this individual is a member.
     *
     * @return a {@code Stream} of {@link OntDisjoint.Individuals}
     */
    @Override
    default Stream disjoints() {
        return getModel().ontObjects(OntDisjoint.Individuals.class).filter(d -> d.members().anyMatch(this::equals));
    }

    /**
     * Lists all different individuals.
     * The pattern to search for is {@code thisIndividual owl:differentFrom otherIndividual},
     * where {@code otherIndividual} is one of the returned.
     *
     * @return {@code Stream} of {@link OntIndividual}s
     * @see OntDisjoint.Individuals
     */
    default Stream differentIndividuals() {
        return objects(OWL2.differentFrom, OntIndividual.class);
    }

    /**
     * Lists all positive assertions for this individual.
     *
     * @return {@code Stream} of {@link OntStatement}s
     */
    default Stream positiveAssertions() {
        return statements().filter(s -> s.getPredicate().canAs(OntNamedProperty.class));
    }

    /**
     * Lists all positive property assertions for this individual and the given predicate.
     *
     * @param predicate {@link OntNamedProperty} or {@code null}
     * @return {@code Stream} of {@link OntStatement}s
     */
    default Stream positiveAssertions(OntNamedProperty predicate) {
        return statements(predicate);
    }

    /**
     * Lists all negative property assertions for this individual.
     *
     * @return {@code Stream} of {@link OntNegativeAssertion negative property assertion}s
     */
    default Stream negativeAssertions() {
        return getModel().statements(null, OWL2.sourceIndividual, this)
                .map(x -> x.getSubject().getAs(OntNegativeAssertion.class))
                .filter(Objects::nonNull);
    }

    /**
     * Lists all negative property assertions for this individual and the given property.
     *
     * @param property {@link OntRelationalProperty} or {@code null}
     * @return {@code Stream} of {@link OntNegativeAssertion negative property assertion}s
     */
    default Stream negativeAssertions(OntRelationalProperty property) {
        Stream res = negativeAssertions();
        if (property == null) {
            return res;
        }
        return res.filter(x -> property.equals(x.getProperty()));
    }

    /**
     * Creates and returns a class-assertion statement {@code a rdf:type C}, where {@code a} is this individual.
     *
     * @param clazz {@link OntClass}, not {@code null}
     * @return {@link OntStatement} to allow subsequent annotations adding
     * @see #attachClass(OntClass)
     * @see #detachClass(Resource)
     */
    default OntStatement addClassAssertion(OntClass clazz) {
        return addStatement(RDF.type, clazz);
    }

    /**
     * Adds a {@link OWL2#differentFrom owl:differentFrom} individual statement.
     *
     * @param other {@link OntIndividual}, not {@code null}
     * @return {@link OntStatement} to provide the ability to add annotations subsequently
     * @see #addDifferentIndividual(OntIndividual)
     * @see #removeDifferentIndividual(Resource)
     * @see OntDisjoint.Individuals
     */
    default OntStatement addDifferentFromStatement(OntIndividual other) {
        return addStatement(OWL2.differentFrom, other);
    }

    /**
     * Adds a same individual reference.
     *
     * @param other {@link OntIndividual}, not {@code null}
     * @return {@link OntStatement} to allow subsequent annotations adding
     * @see #addSameIndividual(OntIndividual)
     * @see #removeSameIndividual(Resource)
     * @see 9.6.1 Individual Equality
     */
    default OntStatement addSameAsStatement(OntIndividual other) {
        return addStatement(OWL2.sameAs, other);
    }

    /**
     * Adds a type (class expression) to this individual.
     *
     * @param clazz {@link OntClass}
     * @return this instance to allow cascading calls
     * @see #addClassAssertion(OntClass)
     * @see #detachClass(Resource)
     */
    default OntIndividual attachClass(OntClass clazz) {
        addClassAssertion(clazz);
        return this;
    }

    /**
     * Adds a {@link OWL2#differentFrom owl:differentFrom} individual statement
     * and returns this object itself to allow cascading calls.
     *
     * @param other {@link OntIndividual}, not {@code null}
     * @return this instance to allow cascading calls
     * @see #addDifferentFromStatement(OntIndividual)
     * @see #removeDifferentIndividual(Resource)
     * @see OntDisjoint.Individuals
     * @see 9.6.2 Individual Inequality
     */
    default OntIndividual addDifferentIndividual(OntIndividual other) {
        addDifferentFromStatement(other);
        return this;
    }

    /**
     * Adds a {@link OWL2#sameAs owl:sameAs} individual statement
     * and returns this object itself to allow cascading calls.
     *
     * @param other other {@link OntIndividual}, not {@code null}
     * @return this instance to allow cascading calls
     * @see #addSameAsStatement(OntIndividual)
     * @see #removeSameIndividual(Resource)
     */
    default OntIndividual addSameIndividual(OntIndividual other) {
        addSameAsStatement(other);
        return this;
    }

    /**
     * Adds annotation assertion {@code AnnotationAssertion(A s t)}.
     * In general case it is {@code s A t}, where {@code s} is IRI or anonymous individual,
     * {@code A} - annotation property, and {@code t} - IRI, anonymous individual, or literal.
     *
     * @param property {@link OntAnnotationProperty}
     * @param value    {@link RDFNode} (IRI, anonymous individual, or literal)
     * @return this individual to allow cascading calls
     * @see #addAnnotation(OntAnnotationProperty, RDFNode)
     * @see #removeAssertion(OntNamedProperty, RDFNode)
     */
    default OntIndividual addAssertion(OntAnnotationProperty property, RDFNode value) {
        return addProperty(property, value);
    }

    /**
     * Adds a positive data property assertion {@code a R v}.
     *
     * @param property {@link OntDataProperty}
     * @param value    {@link Literal}
     * @return this individual to allow cascading calls
     * @see #removeAssertion(OntNamedProperty, RDFNode)
     */
    default OntIndividual addAssertion(OntDataProperty property, Literal value) {
        return addProperty(property, value);
    }

    /**
     * Adds a positive object property assertion {@code a1 PN a2}.
     *
     * @param property {@link OntObjectProperty.Named} named object property
     * @param value    {@link OntIndividual} other individual
     * @return this individual to allow cascading calls
     * @see #removeAssertion(OntNamedProperty, RDFNode)
     */
    default OntIndividual addAssertion(OntObjectProperty.Named property, OntIndividual value) {
        return addProperty(property, value);
    }

    /**
     * Adds a property assertion statement.
     * Caution: this method offers a way to add a statement that is contrary to the OWL2 specification.
     * For example, it is possible to add {@link OntObjectProperty.Named object property}-{@link Literal literal} pair,
     * that is not object property assertion.
     *
     * @param property {@link OntNamedProperty}, not {@code null}
     * @param value    {@link RDFNode}, not {@code null}
     * @return this instance to allow cascading calls
     * @see Resource#addProperty(Property, RDFNode)
     * @see #removeAssertion(OntNamedProperty, RDFNode)
     */
    default OntIndividual addProperty(OntNamedProperty property, RDFNode value) {
        addStatement(property, value);
        return this;
    }

    /**
     * Adds a negative object property assertion.
     * 
     * Functional syntax: {@code NegativeObjectPropertyAssertion(P a1 a2)}
     * RDF Syntax:
     * {@code
     * _:x rdf:type owl:NegativePropertyAssertion .
     * _:x owl:sourceIndividual a1 .
     * _:x owl:assertionProperty P .
     * _:x owl:targetIndividual a2 .
     * }
     * 
* * @param property {@link OntObjectProperty} * @param value {@link OntIndividual} other individual * @return this individual to allow cascading calls */ default OntIndividual addNegativeAssertion(OntObjectProperty property, OntIndividual value) { property.addNegativeAssertion(this, value); return this; } /** * Adds a negative data property assertion. *
     * Functional syntax: {@code NegativeDataPropertyAssertion(R a v)}
     * RDF Syntax:
     * {@code
     * _:x rdf:type owl:NegativePropertyAssertion.
     * _:x owl:sourceIndividual a .
     * _:x owl:assertionProperty R .
     * _:x owl:targetValue v .
     * }
     * 
* * @param property {@link OntDataProperty} * @param value {@link Literal} * @return this individual to allow cascading calls */ default OntIndividual addNegativeAssertion(OntDataProperty property, Literal value) { property.addNegativeAssertion(this, value); return this; } /** * Removes a positive property assertion including its annotation. * * @param property {@link OntNamedProperty}, can be {@code null} to remove all positive property assertions * @param value {@link RDFNode} (either {@link OntIndividual} or {@link Literal}), * can be {@code null} to remove all assertions for the predicate {@code property} * @return this instance to allow cascading calls * @see OntObject#remove(Property, RDFNode) * @see #addProperty(OntNamedProperty, RDFNode) */ default OntIndividual removeAssertion(OntNamedProperty property, RDFNode value) { statements(property) .filter(x -> x.getPredicate().canAs(OntNamedProperty.class) && (value == null || value.equals(x.getObject())) ) .toList() .forEach(x -> x.getModel().remove(x.clearAnnotations())); return this; } /** * Removes a negative property assertion including its annotation. * * @param property {@link OntNamedProperty}, can be {@code null} to remove all negative property assertions * @param value {@link RDFNode} (either {@link OntIndividual} or {@link Literal}), * can be {@code null} to remove all assertions for the predicate {@code property} * @return this instance to allow cascading calls */ default OntIndividual removeNegativeAssertion(OntRelationalProperty property, RDFNode value) { negativeAssertions(property) .filter(x -> value == null || value.equals(x.getTarget())) .toList() .forEach(x -> getModel().removeOntObject(x)); return this; } /** * Removes a different individual statement for this and specified individuals, * including the statement's annotation. * No-op in case no different individuals are found. * Removes all triples with the predicate {@code owl:differentFrom} if {@code null} is specified. * * @param other {@link Resource} or {@code null} to remove all different individuals * @return this instance to allow cascading calls * @see #addDifferentFromStatement(OntIndividual) * @see #addDifferentIndividual(OntIndividual) * @see OntDisjoint.Individuals */ default OntIndividual removeDifferentIndividual(Resource other) { remove(OWL2.differentFrom, other); return this; } /** * Removes a same individual statement for this and specified individuals, * including the statement's annotation. * No-op in case no same individuals are found. * Removes all triples with the predicate {@code owl:sameAs} if {@code null} is specified. * * @param other {@link Resource} or {@code null} to remove all same individuals * @return this instance to allow cascading calls * @see #addSameAsStatement(OntIndividual) * @see #addSameIndividual(OntIndividual) */ default OntIndividual removeSameIndividual(Resource other) { remove(OWL2.sameAs, other); return this; } /** * {@inheritDoc} */ @Override default OntIndividual addComment(String txt) { return addComment(txt, null); } /** * {@inheritDoc} */ @Override default OntIndividual addComment(String txt, String lang) { return annotate(getModel().getRDFSComment(), txt, lang); } /** * {@inheritDoc} */ @Override default OntIndividual addLabel(String txt) { return addLabel(txt, null); } /** * {@inheritDoc} */ @Override default OntIndividual addLabel(String txt, String lang) { return annotate(getModel().getRDFSLabel(), txt, lang); } /** * {@inheritDoc} */ @Override default OntIndividual annotate(OntAnnotationProperty predicate, String txt, String lang) { return annotate(predicate, getModel().createLiteral(txt, lang)); } /** * {@inheritDoc} */ @Override default OntIndividual annotate(OntAnnotationProperty predicate, RDFNode value) { addAnnotation(predicate, value); return this; } /** * An interface for Named Individual which is an {@link OWL2 Entity OntEntity}. * * @see 5.6.1 Named Individuals */ interface Named extends OntIndividual, OntEntity { @Override default Named asNamed() { return this; } } /** * An interface for Anonymous Individuals. * The anonymous individual is a blank node ({@code _:a}) which satisfies one of the following conditions: *
    *
  • it has a class declaration (i.e. there is a triple {@code _:a rdf:type C}, * where {@code C} is a {@link OntClass class expression})
  • *
  • it is a subject or an object in a statement with predicate * {@link OWL2#sameAs owl:sameAs} or {@link OWL2#differentFrom owl:differentFrom}
  • *
  • it is contained in a {@code rdf:List} with predicate {@code owl:distinctMembers} or {@code owl:members} * in a blank node with {@code rdf:type = owl:AllDifferent}, see {@link OntDisjoint.Individuals}
  • *
  • it is contained in a {@code rdf:List} with predicate {@code owl:oneOf} * in a blank node with {@code rdf:type = owl:Class}, see {@link OntClass.OneOf}
  • *
  • it is a part of {@link OntNegativeAssertion owl:NegativePropertyAssertion} section with predicates * {@link OWL2#sourceIndividual owl:sourceIndividual} or {@link OWL2#targetIndividual owl:targetIndividual}
  • *
  • it is an object with predicate {@code owl:hasValue} inside {@code _:x rdf:type owl:Restriction} * (see {@link OntClass.ObjectHasValue Object Property HasValue Restriction})
  • *
  • it is a subject or an object in a statement where predicate is * an uri-resource with {@code rdf:type = owl:AnnotationProperty} * (i.e. {@link OntAnnotationProperty annotation property} assertion {@code s A t})
  • *
  • it is a subject in a triple which corresponds data property assertion {@code _:a R v} * (where {@code R} is a {@link OntDataProperty datatype property}, {@code v} is a {@link Literal literal})
  • *
  • it is a subject or an object in a triple which corresponds object property assertion {@code _:a1 PN _:a2} * (where {@code PN} is a {@link OntObjectProperty.Named named object property}, and {@code _:ai} are individuals)
  • *
* * @see 5.6.2 Anonymous Individuals */ interface Anonymous extends OntIndividual { /** * {@inheritDoc} * For an anonymous individual, a primary class assertion is also a definition, so its deletion is prohibited. * * @param clazz {@link OntClass}, not {@code null} * @return this instance to allow cascading calls * @throws OntJenaException in case the individual has only one class assertion, and it is for the given class */ @Override Anonymous detachClass(Resource clazz) throws OntJenaException; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy