diff --git a/owlapy/model/__init__.py b/owlapy/model/__init__.py index c3451014..5811cfa2 100644 --- a/owlapy/model/__init__.py +++ b/owlapy/model/__init__.py @@ -1,2280 +1,286 @@ -"""@TODO: CD: This is not a python code. We should refactor this model module.""" - -from abc import ABCMeta, abstractmethod -from functools import total_ordering -from itertools import combinations -from typing import Generic, Iterable, Sequence, Set, TypeVar, Union, Final, Optional, Protocol, ClassVar, List -from pandas import Timedelta -from datetime import datetime, date - -from owlapy.vocab import OWLRDFVocabulary, XSDVocabulary, OWLFacet -from owlapy._utils import MOVE -from owlapy.owlobject import OWLObject,OWLEntity -from owlapy.owl_annotation import OWLAnnotationObject, OWLAnnotationSubject, OWLAnnotationValue -from owlapy.iri import IRI -from owlapy.has import HasIndex, HasIRI, HasOperands, HasFiller, HasCardinality -from owlapy.owl_class_expression import OWLNaryBooleanClassExpression, OWLClassExpression, OWLObjectComplementOf, OWLAnonymousClassExpression, OWLBooleanClassExpression, OWLPropertyRange, OWLDataRange, OWLClass, OWLObjectUnionOf, OWLObjectIntersectionOf -from owlapy.owl_property import OWLObjectPropertyExpression, OWLProperty, OWLPropertyExpression, OWLDataPropertyExpression, OWLDataProperty, OWLObjectProperty -from owlapy.owl_restriction import (OWLRestriction,OWLObjectAllValuesFrom, OWLObjectSomeValuesFrom, OWLQuantifiedRestriction, OWLQuantifiedObjectRestriction, - OWLObjectRestriction, OWLHasValueRestriction, OWLDataRestriction, OWLCardinalityRestriction, OWLObjectMinCardinality, OWLObjectCardinalityRestriction,OWLObjectHasSelf,OWLObjectMaxCardinality,OWLObjectExactCardinality) - -MOVE(OWLObject, OWLAnnotationObject, OWLAnnotationSubject, OWLAnnotationValue, HasIRI, IRI) - -_T = TypeVar('_T') #: -_C = TypeVar('_C', bound='OWLObject') #: -_P = TypeVar('_P', bound='OWLPropertyExpression') #: -_R = TypeVar('_R', bound='OWLPropertyRange') #: -Literals = Union['OWLLiteral', int, float, bool, Timedelta, datetime, date, str] #: - - -class OWLIndividual(OWLObject, metaclass=ABCMeta): - """Represents a named or anonymous individual.""" - __slots__ = () - pass - - -class OWLObjectHasValue(OWLHasValueRestriction[OWLIndividual], OWLObjectRestriction): - """Represents an ObjectHasValue class expression in the OWL 2 Specification.""" - __slots__ = '_property', '_v' - type_index: Final = 3007 - - _property: OWLObjectPropertyExpression - _v: OWLIndividual - - def __init__(self, property: OWLObjectPropertyExpression, individual: OWLIndividual): - """ - Args: - property: The property that the restriction acts along. - individual: Individual for restriction. - - Returns: - A HasValue restriction with specified property and value - """ - super().__init__(individual) - self._property = property - - def get_property(self) -> OWLObjectPropertyExpression: - # documented in parent - return self._property - - def as_some_values_from(self) -> OWLClassExpression: - """A convenience method that obtains this restriction as an existential restriction with a nominal filler. - - Returns: - The existential equivalent of this value restriction. simp(HasValue(p a)) = some(p {a}). - """ - return OWLObjectSomeValuesFrom(self.get_property(), OWLObjectOneOf(self.get_filler())) - - def __repr__(self): - return f'OWLObjectHasValue(property={self.get_property()}, individual={self._v})' - - -class OWLObjectOneOf(OWLAnonymousClassExpression, HasOperands[OWLIndividual]): - """Represents an ObjectOneOf class expression in the OWL 2 Specification.""" - __slots__ = '_values' - type_index: Final = 3004 - - def __init__(self, values: Union[OWLIndividual, Iterable[OWLIndividual]]): - if isinstance(values, OWLIndividual): - self._values = values, - else: - for _ in values: - assert isinstance(_, OWLIndividual) - self._values = tuple(values) - - def individuals(self) -> Iterable[OWLIndividual]: - """Gets the individuals that are in the oneOf. These individuals represent the exact instances (extension) - of this class expression. - - Returns: - The individuals that are the values of this {@code ObjectOneOf} class expression. - """ - yield from self._values - - def operands(self) -> Iterable[OWLIndividual]: - # documented in parent - yield from self.individuals() - - def as_object_union_of(self) -> OWLClassExpression: - """Simplifies this enumeration to a union of singleton nominals. - - Returns: - This enumeration in a more standard DL form. - simp({a}) = {a} simp({a0, ... , {an}) = unionOf({a0}, ... , {an}) - """ - if len(self._values) == 1: - return self - return OWLObjectUnionOf(map(lambda _: OWLObjectOneOf(_), self.individuals())) - - def __hash__(self): - return hash(self._values) - - def __eq__(self, other): - if type(other) == type(self): - return self._values == other._values - return NotImplemented - - def __repr__(self): - return f'OWLObjectOneOf({self._values})' - - -class OWLNamedIndividual(OWLIndividual, OWLEntity): - """Represents a Named Individual in the OWL 2 Specification.""" - __slots__ = '_iri' - type_index: Final = 1005 - - _iri: IRI - - def __init__(self, iri: Union[IRI, str]): - """Gets an instance of OWLNamedIndividual that has the specified IRI. - - Args: - iri: an instance of IRI Class or a string representing the iri - - Returns: - An OWLNamedIndividual that has the specified IRI. - """ - if isinstance(iri, IRI): - self._iri = iri - else: - self._iri = IRI.create(iri) - - def get_iri(self) -> IRI: - # TODO:CD: can be deprecated - # documented in parent - return self._iri - - @property - def iri(self): - return self._iri - - @property - def str(self): - return self._iri.as_str() - - -_M = TypeVar('_M', bound='OWLOntologyManager') #: - - -class OWLOntologyID: - """An object that identifies an ontology. Since OWL 2, ontologies do not have to have an ontology IRI, or if they - have an ontology IRI then they can optionally also have a version IRI. Instances of this OWLOntologyID class bundle - identifying information of an ontology together. If an ontology doesn't have an ontology IRI then we say that it is - "anonymous". - """ - __slots__ = '_ontology_iri', '_version_iri' - - _ontology_iri: Optional[IRI] - _version_iri: Optional[IRI] - - def __init__(self, ontology_iri: Optional[IRI] = None, version_iri: Optional[IRI] = None): - """Constructs an ontology identifier specifying the ontology IRI and version IRI. - - Args: - ontology_iri: The ontology IRI (optional). - version_iri: The version IRI (must be None if no ontology_iri is provided). - """ - self._ontology_iri = ontology_iri - self._version_iri = version_iri - - def get_ontology_iri(self) -> Optional[IRI]: - """Gets the ontology IRI. - - Returns: - Ontology IRI. If the ontology is anonymous, it will return None. - """ - return self._ontology_iri - - def get_version_iri(self) -> Optional[IRI]: - """Gets the version IRI. - - Returns: - Version IRI or None. - """ - return self._version_iri - - def get_default_document_iri(self) -> Optional[IRI]: - """Gets the IRI which is used as a default for the document that contain a representation of an ontology with - this ID. This will be the version IRI if there is an ontology IRI and version IRI, else it will be the ontology - IRI if there is an ontology IRI but no version IRI, else it will be None if there is no ontology IRI. See - Ontology Documents in the OWL 2 Structural Specification. - - Returns: - the IRI that can be used as a default for an ontology document, or None. - """ - if self._ontology_iri is not None: - if self._version_iri is not None: - return self._version_iri - return self._ontology_iri - - def is_anonymous(self) -> bool: - return self._ontology_iri is None - - def __repr__(self): - return f"OWLOntologyID({repr(self._ontology_iri)}, {repr(self._version_iri)})" - - def __eq__(self, other): - if type(other) is type(self): - return self._ontology_iri == other._ontology_iri and self._version_iri == other._version_iri - return NotImplemented - - -class OWLAxiom(OWLObject, metaclass=ABCMeta): - """Represents Axioms in the OWL 2 Specification. - - An OWL ontology contains a set of axioms. These axioms can be annotation axioms, declaration axioms, imports axioms - or logical axioms. - """ - __slots__ = '_annotations' - - _annotations: List['OWLAnnotation'] - - def __init__(self, annotations: Optional[Iterable['OWLAnnotation']] = None): - self._annotations = list(annotations) if annotations is not None else list() - - def annotations(self) -> Optional[List['OWLAnnotation']]: - return self._annotations - - def is_annotated(self) -> bool: - return self._annotations is not None and len(self._annotations) > 0 - - def is_logical_axiom(self) -> bool: - return False - - def is_annotation_axiom(self) -> bool: - return False - # TODO: XXX - - -class OWLDatatype(OWLEntity, OWLDataRange): - """Represents a Datatype (named data range) in the OWL 2 Specification.""" - __slots__ = '_iri' - - type_index: Final = 4001 - - _iri: IRI - - def __init__(self, iri: Union[IRI, HasIRI]): - """Gets an instance of OWLDatatype that has the specified IRI. - - Args: - iri: The IRI. - """ - if isinstance(iri, HasIRI): - self._iri = iri.get_iri() - else: - assert isinstance(iri, IRI) - self._iri = iri - - def get_iri(self) -> 'IRI': - # documented in parent - return self._iri - - -class OWLDatatypeRestriction(OWLDataRange): - """Represents a DatatypeRestriction data range in the OWL 2 Specification.""" - __slots__ = '_type', '_facet_restrictions' - - type_index: Final = 4006 - - _type: OWLDatatype - _facet_restrictions: Sequence['OWLFacetRestriction'] - - def __init__(self, type_: OWLDatatype, facet_restrictions: Union['OWLFacetRestriction', - Iterable['OWLFacetRestriction']]): - self._type = type_ - if isinstance(facet_restrictions, OWLFacetRestriction): - facet_restrictions = facet_restrictions, - self._facet_restrictions = tuple(facet_restrictions) - - def get_datatype(self) -> OWLDatatype: - return self._type - - def get_facet_restrictions(self) -> Sequence['OWLFacetRestriction']: - return self._facet_restrictions - - def __eq__(self, other): - if type(other) is type(self): - return self._type == other._type \ - and self._facet_restrictions == other._facet_restrictions - return NotImplemented - - def __hash__(self): - return hash((self._type, self._facet_restrictions)) - - def __repr__(self): - return f'OWLDatatypeRestriction({repr(self._type)}, {repr(self._facet_restrictions)})' - - -class OWLFacetRestriction(OWLObject): - """A facet restriction is used to restrict a particular datatype.""" - - __slots__ = '_facet', '_literal' - - type_index: Final = 4007 - - _facet: OWLFacet - _literal: 'OWLLiteral' - - def __init__(self, facet: OWLFacet, literal: Literals): - self._facet = facet - if isinstance(literal, OWLLiteral): - self._literal = literal - else: - self._literal = OWLLiteral(literal) - - def get_facet(self) -> OWLFacet: - return self._facet - - def get_facet_value(self) -> 'OWLLiteral': - return self._literal - - def __eq__(self, other): - if type(other) is type(self): - return self._facet == other._facet and self._literal == other._literal - return NotImplemented - - def __hash__(self): - return hash((self._facet, self._literal)) - - def __repr__(self): - return f'OWLFacetRestriction({self._facet}, {repr(self._literal)})' - - -class OWLLiteral(OWLAnnotationValue, metaclass=ABCMeta): - """Represents a Literal in the OWL 2 Specification.""" - __slots__ = () - - type_index: Final = 4008 - - def __new__(cls, value, type_: Optional[OWLDatatype] = None): - """Convenience method that obtains a literal. - - Args: - value: The value of the literal. - type_: The datatype of the literal. - """ - if type_ is not None: - if type_ == BooleanOWLDatatype: - return super().__new__(_OWLLiteralImplBoolean) - elif type_ == IntegerOWLDatatype: - return super().__new__(_OWLLiteralImplInteger) - elif type_ == DoubleOWLDatatype: - return super().__new__(_OWLLiteralImplDouble) - elif type_ == StringOWLDatatype: - return super().__new__(_OWLLiteralImplString) - elif type_ == DateOWLDatatype: - return super().__new__(_OWLLiteralImplDate) - elif type_ == DateTimeOWLDatatype: - return super().__new__(_OWLLiteralImplDateTime) - elif type_ == DurationOWLDatatype: - return super().__new__(_OWLLiteralImplDuration) - else: - return super().__new__(_OWLLiteralImpl) - if isinstance(value, bool): - return super().__new__(_OWLLiteralImplBoolean) - elif isinstance(value, int): - return super().__new__(_OWLLiteralImplInteger) - elif isinstance(value, float): - return super().__new__(_OWLLiteralImplDouble) - elif isinstance(value, str): - return super().__new__(_OWLLiteralImplString) - elif isinstance(value, datetime): - return super().__new__(_OWLLiteralImplDateTime) - elif isinstance(value, date): - return super().__new__(_OWLLiteralImplDate) - elif isinstance(value, Timedelta): - return super().__new__(_OWLLiteralImplDuration) - # TODO XXX - raise NotImplementedError(value) - - def get_literal(self) -> str: - """Gets the lexical value of this literal. Note that the language tag is not included. - - Returns: - The lexical value of this literal. - """ - return str(self._v) - - def is_boolean(self) -> bool: - """Whether this literal is typed as boolean.""" - return False - - def parse_boolean(self) -> bool: - """Parses the lexical value of this literal into a bool. The lexical value of this literal should be in the - lexical space of the boolean datatype ("http://www.w3.org/2001/XMLSchema#boolean"). - - Returns: - A bool value that is represented by this literal. - """ - raise ValueError - - def is_double(self) -> bool: - """Whether this literal is typed as double.""" - return False - - def parse_double(self) -> float: - """Parses the lexical value of this literal into a double. The lexical value of this literal should be in the - lexical space of the double datatype ("http://www.w3.org/2001/XMLSchema#double"). - - Returns: - A double value that is represented by this literal. - """ - raise ValueError - - def is_integer(self) -> bool: - """Whether this literal is typed as integer.""" - return False - - def parse_integer(self) -> int: - """Parses the lexical value of this literal into an integer. The lexical value of this literal should be in the - lexical space of the integer datatype ("http://www.w3.org/2001/XMLSchema#integer"). - - Returns: - An integer value that is represented by this literal. - """ - raise ValueError - - def is_string(self) -> bool: - """Whether this literal is typed as string.""" - return False - - def parse_string(self) -> str: - """Parses the lexical value of this literal into a string. The lexical value of this literal should be in the - lexical space of the string datatype ("http://www.w3.org/2001/XMLSchema#string"). - - Returns: - A string value that is represented by this literal. - """ - raise ValueError - - def is_date(self) -> bool: - """Whether this literal is typed as date.""" - return False - - def parse_date(self) -> date: - """Parses the lexical value of this literal into a date. The lexical value of this literal should be in the - lexical space of the date datatype ("http://www.w3.org/2001/XMLSchema#date"). - - Returns: - A date value that is represented by this literal. - """ - raise ValueError - - def is_datetime(self) -> bool: - """Whether this literal is typed as dateTime.""" - return False - - def parse_datetime(self) -> datetime: - """Parses the lexical value of this literal into a datetime. The lexical value of this literal should be in the - lexical space of the dateTime datatype ("http://www.w3.org/2001/XMLSchema#dateTime"). - - Returns: - A datetime value that is represented by this literal. - """ - raise ValueError - - def is_duration(self) -> bool: - """Whether this literal is typed as duration.""" - return False - - def parse_duration(self) -> Timedelta: - """Parses the lexical value of this literal into a Timedelta. The lexical value of this literal should be in the - lexical space of the duration datatype ("http://www.w3.org/2001/XMLSchema#duration"). - - Returns: - A Timedelta value that is represented by this literal. - """ - raise ValueError - - # noinspection PyMethodMayBeStatic - def is_literal(self) -> bool: - # documented in parent - return True - - def as_literal(self) -> 'OWLLiteral': - # documented in parent - return self - - def to_python(self) -> Literals: - return self._v - - @abstractmethod - def get_datatype(self) -> OWLDatatype: - """Gets the OWLDatatype which types this literal. - - Returns: - The OWLDatatype that types this literal. - """ - pass - - -@total_ordering -class _OWLLiteralImplDouble(OWLLiteral): - __slots__ = '_v' - - _v: float - - def __init__(self, value, type_=None): - assert type_ is None or type_ == DoubleOWLDatatype - if not isinstance(value, float): - value = float(value) - self._v = value - - def __eq__(self, other): - if type(other) is type(self): - return self._v == other._v - return NotImplemented - - def __lt__(self, other): - if type(other) is type(self): - return self._v < other._v - return NotImplemented - - def __hash__(self): - return hash(self._v) - - def __repr__(self): - return f'OWLLiteral({self._v})' - - def is_double(self) -> bool: - return True - - def parse_double(self) -> float: - # documented in parent - return self._v - - # noinspection PyMethodMayBeStatic - def get_datatype(self) -> OWLDatatype: - # documented in parent - return DoubleOWLDatatype - - -@total_ordering -class _OWLLiteralImplInteger(OWLLiteral): - __slots__ = '_v' - - _v: int - - def __init__(self, value, type_=None): - assert type_ is None or type_ == IntegerOWLDatatype - if not isinstance(value, int): - value = int(value) - self._v = value - - def __eq__(self, other): - if type(other) is type(self): - return self._v == other._v - return NotImplemented - - def __lt__(self, other): - if type(other) is type(self): - return self._v < other._v - return NotImplemented - - def __hash__(self): - return hash(self._v) - - def __repr__(self): - return f'OWLLiteral({self._v})' - - def is_integer(self) -> bool: - return True - - def parse_integer(self) -> int: - # documented in parent - return self._v - - # noinspection PyMethodMayBeStatic - def get_datatype(self) -> OWLDatatype: - # documented in parent - return IntegerOWLDatatype - - -class _OWLLiteralImplBoolean(OWLLiteral): - __slots__ = '_v' - - _v: bool - - def __init__(self, value, type_=None): - assert type_ is None or type_ == BooleanOWLDatatype - if not isinstance(value, bool): - from distutils.util import strtobool - value = bool(strtobool(value)) - self._v = value - - def __eq__(self, other): - if type(other) is type(self): - return self._v == other._v - return NotImplemented - - def __hash__(self): - return hash(self._v) - - def __repr__(self): - return f'OWLLiteral({self._v})' - - def is_boolean(self) -> bool: - return True - - def parse_boolean(self) -> bool: - # documented in parent - return self._v - - # noinspection PyMethodMayBeStatic - def get_datatype(self) -> OWLDatatype: - # documented in parent - return BooleanOWLDatatype - - -@total_ordering -class _OWLLiteralImplString(OWLLiteral): - __slots__ = '_v' - - _v: str - - def __init__(self, value, type_=None): - assert type_ is None or type_ == StringOWLDatatype - if not isinstance(value, str): - value = str(value) - self._v = value - - def __eq__(self, other): - if type(other) is type(self): - return self._v == other._v - return NotImplemented - - def __lt__(self, other): - if type(other) is type(self): - return self._v < other._v - return NotImplemented - - def __len__(self): - return len(self._v) - - def __hash__(self): - return hash(self._v) - - def __repr__(self): - return f'OWLLiteral({self._v})' - - def is_string(self) -> bool: - return True - - def parse_string(self) -> str: - # documented in parent - return self._v - - # noinspection PyMethodMayBeStatic - def get_datatype(self) -> OWLDatatype: - # documented in parent - return StringOWLDatatype - - -@total_ordering -class _OWLLiteralImplDate(OWLLiteral): - __slots__ = '_v' - - _v: date - - def __init__(self, value, type_=None): - assert type_ is None or type_ == DateOWLDatatype - if not isinstance(value, date): - value = date.fromisoformat(value) - self._v = value - - def __eq__(self, other): - if type(other) is type(self): - return self._v == other._v - return NotImplemented - - def __lt__(self, other): - if type(other) is type(self): - return self._v < other._v - return NotImplemented - - def __hash__(self): - return hash(self._v) - - def __repr__(self): - return f'OWLLiteral({self._v})' - - def is_date(self) -> bool: - return True - - def parse_date(self) -> date: - # documented in parent - return self._v - - # noinspection PyMethodMayBeStatic - def get_datatype(self) -> OWLDatatype: - # documented in parent - return DateOWLDatatype - - -@total_ordering -class _OWLLiteralImplDateTime(OWLLiteral): - __slots__ = '_v' - - _v: datetime - - def __init__(self, value, type_=None): - assert type_ is None or type_ == DateTimeOWLDatatype - if not isinstance(value, datetime): - value = value.replace("Z", "+00:00") if isinstance(value, str) and value[-1] == "Z" else value - value = datetime.fromisoformat(value) - self._v = value - - def __eq__(self, other): - if type(other) is type(self): - return self._v == other._v - return NotImplemented - - def __lt__(self, other): - if type(other) is type(self): - return self._v < other._v - return NotImplemented - - def __hash__(self): - return hash(self._v) - - def __repr__(self): - return f'OWLLiteral({self._v})' - - def is_datetime(self) -> bool: - return True - - def parse_datetime(self) -> datetime: - # documented in parent - return self._v - - # noinspection PyMethodMayBeStatic - def get_datatype(self) -> OWLDatatype: - # documented in parent - return DateTimeOWLDatatype - - -@total_ordering -class _OWLLiteralImplDuration(OWLLiteral): - __slots__ = '_v' - - _v: Timedelta - - def __init__(self, value, type_=None): - assert type_ is None or type_ == DurationOWLDatatype - if not isinstance(value, Timedelta): - value = Timedelta(value) - self._v = value - - def get_literal(self) -> str: - return self._v.isoformat() - - def __eq__(self, other): - if type(other) is type(self): - return self._v == other._v - return NotImplemented - - def __lt__(self, other): - if type(other) is type(self): - return self._v < other._v - return NotImplemented - - def __hash__(self): - return hash(self._v) - - def __repr__(self): - return f'OWLLiteral({self._v})' - - def is_duration(self) -> bool: - return True - - def parse_duration(self) -> Timedelta: - # documented in parent - return self._v - - # noinspection PyMethodMayBeStatic - def get_datatype(self) -> OWLDatatype: - # documented in parent - return DurationOWLDatatype - - -class _OWLLiteralImpl(OWLLiteral): - __slots__ = '_v', '_datatype' - - def __init__(self, v, type_: OWLDatatype): - assert isinstance(type_, OWLDatatype) - self._v = v - self._datatype = type_ - - def get_datatype(self) -> OWLDatatype: - return self._datatype - - def __eq__(self, other): - if type(other) is type(self) and other.get_datatype() == self.get_datatype(): - return self._v == other._v - return NotImplemented - - def __hash__(self): - return hash((self._v, self._datatype)) - - def __repr__(self): - return f'OWLLiteral({repr(self._v)}, {self._datatype})' - - -class OWLQuantifiedDataRestriction(OWLQuantifiedRestriction[OWLDataRange], - OWLDataRestriction, metaclass=ABCMeta): - """Represents a quantified data restriction.""" - __slots__ = () - - _filler: OWLDataRange - - def __init__(self, filler: OWLDataRange): - self._filler = filler - - def get_filler(self) -> OWLDataRange: - # documented in parent (HasFiller) - return self._filler - - -class OWLDataCardinalityRestriction(OWLCardinalityRestriction[OWLDataRange], - OWLQuantifiedDataRestriction, - OWLDataRestriction, metaclass=ABCMeta): - """Represents Data Property Cardinality Restrictions in the OWL 2 specification.""" - __slots__ = () - - _property: OWLDataPropertyExpression - - @abstractmethod - def __init__(self, cardinality: int, property: OWLDataPropertyExpression, filler: OWLDataRange): - super().__init__(cardinality, filler) - self._property = property - - def get_property(self) -> OWLDataPropertyExpression: - # documented in parent - return self._property - - def __repr__(self): - return f"{type(self).__name__}(" \ - f"property={repr(self.get_property())},{self.get_cardinality()},filler={repr(self.get_filler())})" - - def __eq__(self, other): - if type(other) == type(self): - return self._property == other._property \ - and self._cardinality == other._cardinality \ - and self._filler == other._filler - return NotImplemented - - def __hash__(self): - return hash((self._property, self._cardinality, self._filler)) - - -class OWLDataAllValuesFrom(OWLQuantifiedDataRestriction): - """Represents DataAllValuesFrom class expressions in the OWL 2 Specification.""" - __slots__ = '_property' - - type_index: Final = 3013 - - _property: OWLDataPropertyExpression - - def __init__(self, property: OWLDataPropertyExpression, filler: OWLDataRange): - """Gets an OWLDataAllValuesFrom restriction. - - Args: - property: The data property that the restriction acts along. - filler: The data range that is the filler. - - Returns: - An OWLDataAllValuesFrom restriction along the specified property with the specified filler. - """ - super().__init__(filler) - self._property = property - - def __repr__(self): - return f"OWLDataAllValuesFrom(property={repr(self._property)},filler={repr(self._filler)})" - - def __eq__(self, other): - if type(other) is type(self): - return self._filler == other._filler and self._property == other._property - return NotImplemented - - def __hash__(self): - return hash((self._filler, self._property)) - - def get_property(self) -> OWLDataPropertyExpression: - # documented in parent - return self._property - - -class OWLDataComplementOf(OWLDataRange): - """Represents DataComplementOf in the OWL 2 Specification.""" - type_index: Final = 4002 - - _data_range: OWLDataRange - - def __init__(self, data_range: OWLDataRange): - """ - Args: - data_range: Data range to complement. - """ - self._data_range = data_range - - def get_data_range(self) -> OWLDataRange: - """ - Returns: - The wrapped data range. - """ - return self._data_range - - def __repr__(self): - return f"OWLDataComplementOf({repr(self._data_range)})" - - def __eq__(self, other): - if type(other) is type(self): - return self._data_range == other._data_range - return NotImplemented - - def __hash__(self): - return hash(self._data_range) - - -class OWLDataExactCardinality(OWLDataCardinalityRestriction): - """Represents DataExactCardinality restrictions in the OWL 2 Specification.""" - __slots__ = '_cardinality', '_filler', '_property' - - type_index: Final = 3016 - - def __init__(self, cardinality: int, property: OWLDataPropertyExpression, filler: OWLDataRange): - """ - Args: - cardinality: Cannot be negative. - property: The property that the restriction acts along. - filler: Data range for restriction - - Returns: - A DataExactCardinality on the specified property. - """ - super().__init__(cardinality, property, filler) - - def as_intersection_of_min_max(self) -> OWLObjectIntersectionOf: - """Obtains an equivalent form that is a conjunction of a min cardinality and max cardinality restriction. - - Returns: - The semantically equivalent but structurally simpler form (= 1 R D) = >= 1 R D and <= 1 R D. - """ - args = self.get_cardinality(), self.get_property(), self.get_filler() - return OWLObjectIntersectionOf((OWLDataMinCardinality(*args), OWLDataMaxCardinality(*args))) - - -class OWLDataHasValue(OWLHasValueRestriction[OWLLiteral], OWLDataRestriction): - """Represents DataHasValue restrictions in the OWL 2 Specification.""" - __slots__ = '_property' - - type_index: Final = 3014 - - _property: OWLDataPropertyExpression - - def __init__(self, property: OWLDataPropertyExpression, value: OWLLiteral): - """Gets an OWLDataHasValue restriction. - - Args: - property: The data property that the restriction acts along. - filler: The literal value. - - Returns: - An OWLDataHasValue restriction along the specified property with the specified literal. - """ - super().__init__(value) - self._property = property - - def __repr__(self): - return f"OWLDataHasValue(property={repr(self._property)},value={repr(self._v)})" - - def __eq__(self, other): - if type(other) is type(self): - return self._v == other._v and self._property == other._property - return NotImplemented - - def __hash__(self): - return hash((self._v, self._property)) - - def as_some_values_from(self) -> OWLClassExpression: - """A convenience method that obtains this restriction as an existential restriction with a nominal filler. - - Returns: - The existential equivalent of this value restriction. simp(HasValue(p a)) = some(p {a}). - """ - return OWLDataSomeValuesFrom(self.get_property(), OWLDataOneOf(self.get_filler())) - - def get_property(self) -> OWLDataPropertyExpression: - # documented in parent - return self._property - - -class OWLDataMaxCardinality(OWLDataCardinalityRestriction): - """Represents DataMaxCardinality restrictions in the OWL 2 Specification.""" - __slots__ = '_cardinality', '_filler', '_property' - - type_index: Final = 3017 - - def __init__(self, cardinality: int, property: OWLDataPropertyExpression, filler: OWLDataRange): - """ - Args: - cardinality: Cannot be negative. - property: The property that the restriction acts along. - filler: Data range for restriction. - - Returns: - A DataMaxCardinality on the specified property. - """ - super().__init__(cardinality, property, filler) - - -class OWLDataMinCardinality(OWLDataCardinalityRestriction): - """Represents DataMinCardinality restrictions in the OWL 2 Specification.""" - __slots__ = '_cardinality', '_filler', '_property' - - type_index: Final = 3015 - - def __init__(self, cardinality: int, property: OWLDataPropertyExpression, filler: OWLDataRange): - """ - Args: - cardinality: Cannot be negative. - property: The property that the restriction acts along. - filler: Data range for restriction. - - Returns: - A DataMinCardinality on the specified property. - """ - super().__init__(cardinality, property, filler) - - -class OWLDataOneOf(OWLDataRange, HasOperands[OWLLiteral]): - """Represents DataOneOf in the OWL 2 Specification.""" - type_index: Final = 4003 - - _values: Sequence[OWLLiteral] - - def __init__(self, values: Union[OWLLiteral, Iterable[OWLLiteral]]): - if isinstance(values, OWLLiteral): - self._values = values, - else: - for _ in values: - assert isinstance(_, OWLLiteral) - self._values = tuple(values) - - def values(self) -> Iterable[OWLLiteral]: - """Gets the values that are in the oneOf. - - Returns: - The values of this {@code DataOneOf} class expression. - """ - yield from self._values - - def operands(self) -> Iterable[OWLLiteral]: - # documented in parent - yield from self.values() - - def __hash__(self): - return hash(self._values) - - def __eq__(self, other): - if type(other) == type(self): - return self._values == other._values - return NotImplemented - - def __repr__(self): - return f'OWLDataOneOf({self._values})' - - -class OWLDataSomeValuesFrom(OWLQuantifiedDataRestriction): - """Represents a DataSomeValuesFrom restriction in the OWL 2 Specification.""" - __slots__ = '_property' - - type_index: Final = 3012 - - _property: OWLDataPropertyExpression - - def __init__(self, property: OWLDataPropertyExpression, filler: OWLDataRange): - """Gets an OWLDataSomeValuesFrom restriction. - - Args: - property: The data property that the restriction acts along. - filler: The data range that is the filler. - - Returns: - An OWLDataSomeValuesFrom restriction along the specified property with the specified filler. - """ - super().__init__(filler) - self._property = property - - def __repr__(self): - return f"OWLDataSomeValuesFrom(property={repr(self._property)},filler={repr(self._filler)})" - - def __eq__(self, other): - if type(other) is type(self): - return self._filler == other._filler and self._property == other._property - return NotImplemented - - def __hash__(self): - return hash((self._filler, self._property)) - - def get_property(self) -> OWLDataPropertyExpression: - # documented in parent - return self._property - - -class OWLNaryDataRange(OWLDataRange, HasOperands[OWLDataRange]): - """OWLNaryDataRange.""" - __slots__ = () - - _operands: Sequence[OWLDataRange] - - def __init__(self, operands: Iterable[OWLDataRange]): - """ - Args: - operands: Data ranges. - """ - self._operands = tuple(operands) - - def operands(self) -> Iterable[OWLDataRange]: - # documented in parent - yield from self._operands - - def __repr__(self): - return f'{type(self).__name__}({repr(self._operands)})' - - def __eq__(self, other): - if type(other) == type(self): - return self._operands == other._operands - return NotImplemented - - def __hash__(self): - return hash(self._operands) - - -class OWLDataUnionOf(OWLNaryDataRange): - """Represents a DataUnionOf data range in the OWL 2 Specification.""" - __slots__ = '_operands' - type_index: Final = 4005 - - _operands: Sequence[OWLDataRange] - - -class OWLDataIntersectionOf(OWLNaryDataRange): - """Represents DataIntersectionOf in the OWL 2 Specification.""" - __slots__ = '_operands' - type_index: Final = 4004 - - _operands: Sequence[OWLDataRange] - - -class OWLImportsDeclaration(HasIRI): - """Represents an import statement in an ontology.""" - __slots__ = '_iri' - - def __init__(self, import_iri: IRI): - """ - Args: - import_import_iri: Imported ontology. - - Returns: - An imports declaration. - """ - self._iri = import_iri - - def get_iri(self) -> IRI: - """Gets the import IRI. - - Returns: - The import IRI that points to the ontology to be imported. The imported ontology might have this IRI as - its ontology IRI but this is not mandated. For example, an ontology with a non-resolvable ontology IRI - can be deployed at a resolvable URL. - """ - return self._iri - - -class OWLLogicalAxiom(OWLAxiom, metaclass=ABCMeta): - """A base interface of all axioms that affect the logical meaning of an ontology. This excludes declaration axioms - (including imports declarations) and annotation axioms. - """ - __slots__ = () - - def __init__(self, annotations: Optional[Iterable['OWLAnnotation']] = None): - super().__init__(annotations=annotations) - - def is_logical_axiom(self) -> bool: - return True - - -class OWLPropertyAxiom(OWLLogicalAxiom, metaclass=ABCMeta): - """The base interface for property axioms.""" - __slots__ = () - - def __init__(self, annotations: Optional[Iterable['OWLAnnotation']] = None): - super().__init__(annotations=annotations) - - -class OWLObjectPropertyAxiom(OWLPropertyAxiom, metaclass=ABCMeta): - """The base interface for object property axioms.""" - __slots__ = () - - -class OWLDataPropertyAxiom(OWLPropertyAxiom, metaclass=ABCMeta): - """The base interface for data property axioms.""" - __slots__ = () - - -class OWLIndividualAxiom(OWLLogicalAxiom, metaclass=ABCMeta): - """The base interface for individual axioms.""" - __slots__ = () - - def __init__(self, annotations: Optional[Iterable['OWLAnnotation']] = None): - super().__init__(annotations=annotations) - - -class OWLClassAxiom(OWLLogicalAxiom, metaclass=ABCMeta): - """The base interface for class axioms.""" - __slots__ = () - - def __init__(self, annotations: Optional[Iterable['OWLAnnotation']] = None): - super().__init__(annotations=annotations) - - -class OWLDeclarationAxiom(OWLAxiom): - """Represents a Declaration axiom in the OWL 2 Specification. A declaration axiom declares an entity in an ontology. - It doesn't affect the logical meaning of the ontology.""" - __slots__ = '_entity' - - _entity: OWLEntity - - def __init__(self, entity: OWLEntity, annotations: Optional[Iterable['OWLAnnotation']] = None): - self._entity = entity - super().__init__(annotations=annotations) - - def get_entity(self) -> OWLEntity: - return self._entity - - def __eq__(self, other): - if type(other) is type(self): - return self._entity == other._entity and self._annotations == other._annotations - return NotImplemented - - def __hash__(self): - return hash((self._entity, *self._annotations)) - - def __repr__(self): - return f'OWLDeclarationAxiom(entity={self._entity},annotations={self._annotations})' - - -class OWLDatatypeDefinitionAxiom(OWLLogicalAxiom): - """Represents a DatatypeDefinition axiom in the OWL 2 Specification.""" - __slots__ = '_datatype', '_datarange' - - _datatype: OWLDatatype - _datarange: OWLDataRange - - def __init__(self, datatype: OWLDatatype, datarange: OWLDataRange, - annotations: Optional[Iterable['OWLAnnotation']] = None): - self._datatype = datatype - self._datarange = datarange - super().__init__(annotations=annotations) - - def get_datatype(self) -> OWLDatatype: - return self._datatype - - def get_datarange(self) -> OWLDataRange: - return self._datarange - - def __eq__(self, other): - if type(other) is type(self): - return self._datatype == other._datatype and self._datarange == other._datarange \ - and self._annotations == other._annotations - return NotImplemented - - def __hash__(self): - return hash((self._datatype, self._datarange, *self._annotations)) - - def __repr__(self): - return f'OWLDatatypeDefinitionAxiom(datatype={self._datatype},datarange={self._datarange},' \ - f'annotations={self._annotations})' - - -class OWLHasKeyAxiom(OWLLogicalAxiom, HasOperands[OWLPropertyExpression]): - """Represents a HasKey axiom in the OWL 2 Specification.""" - __slots__ = '_class_expression', '_property_expressions' - - _class_expression: OWLClassExpression - _property_expressions: List[OWLPropertyExpression] - - def __init__(self, class_expression: OWLClassExpression, property_expressions: List[OWLPropertyExpression], - annotations: Optional[Iterable['OWLAnnotation']] = None): - self._class_expression = class_expression - self._property_expressions = property_expressions - super().__init__(annotations=annotations) - - def get_class_expression(self) -> OWLClassExpression: - return self._class_expression - - def get_property_expressions(self) -> List[OWLPropertyExpression]: - return self._property_expressions - - def operands(self) -> Iterable[OWLPropertyExpression]: - yield from self._property_expressions - - def __eq__(self, other): - if type(other) is type(self): - return self._class_expression == other._class_expression \ - and self._property_expressions == other._property_expressions \ - and self._annotations == other._annotations - return NotImplemented - - def __hash__(self): - return hash((self._class_expression, *self._property_expressions, *self._annotations)) - - def __repr__(self): - return f'OWLHasKeyAxiom(class_expression={self._class_expression},' \ - f'property_expressions={self._property_expressions},annotations={self._annotations})' - - -class OWLNaryAxiom(Generic[_C], OWLAxiom, metaclass=ABCMeta): - """Represents an axiom that contains two or more operands that could also be represented with multiple pairwise - axioms. - - Args: - _C: Class of contained objects. - """ - __slots__ = () - - @abstractmethod - def as_pairwise_axioms(self) -> Iterable['OWLNaryAxiom[_C]']: - pass - - -# noinspection PyUnresolvedReferences -# noinspection PyDunderSlots -class OWLNaryClassAxiom(OWLClassAxiom, OWLNaryAxiom[OWLClassExpression], metaclass=ABCMeta): - """Represents an axiom that contains two or more operands that could also be represented with - multiple pairwise axioms.""" - __slots__ = '_class_expressions' - _class_expressions: List[OWLClassExpression] - - @abstractmethod - def __init__(self, class_expressions: List[OWLClassExpression], - annotations: Optional[Iterable['OWLAnnotation']] = None): - self._class_expressions = [*class_expressions] - super().__init__(annotations=annotations) - - def class_expressions(self) -> Iterable[OWLClassExpression]: - """Gets all of the top level class expressions that appear in this axiom. - - Returns: - Sorted stream of class expressions that appear in the axiom. - """ - yield from self._class_expressions - - def as_pairwise_axioms(self) -> Iterable['OWLNaryClassAxiom']: - """Gets this axiom as a set of pairwise axioms; if the axiom contains only two operands, - the axiom itself is returned unchanged, including its annotations. - - Returns: - This axiom as a set of pairwise axioms. - """ - if len(self._class_expressions) < 3: - yield self - else: - yield from map(type(self), combinations(self._class_expressions, 2)) - - def __eq__(self, other): - if type(other) is type(self): - return self._class_expressions == other._class_expressions and self._annotations == other._annotations - return NotImplemented - - def __hash__(self): - return hash((*self._class_expressions, *self._annotations)) - - def __repr__(self): - return f'{type(self).__name__}({self._class_expressions},{self._annotations})' - - -class OWLEquivalentClassesAxiom(OWLNaryClassAxiom): - """Represents an EquivalentClasses axiom in the OWL 2 Specification.""" - __slots__ = () - - def __init__(self, class_expressions: List[OWLClassExpression], - annotations: Optional[Iterable['OWLAnnotation']] = None): - super().__init__(class_expressions=class_expressions, annotations=annotations) - - def contains_named_equivalent_class(self) -> bool: - return any(isinstance(ce, OWLClass) for ce in self._class_expressions) - - def contains_owl_nothing(self) -> bool: - return any(isinstance(ce, OWLNothing) for ce in self._class_expressions) - - def contains_owl_thing(self) -> bool: - return any(isinstance(ce, OWLThing) for ce in self._class_expressions) - - def named_classes(self) -> Iterable[OWLClass]: - yield from (ce for ce in self._class_expressions if isinstance(ce, OWLClass)) - - -class OWLDisjointClassesAxiom(OWLNaryClassAxiom): - """Represents a DisjointClasses axiom in the OWL 2 Specification.""" - __slots__ = () - - def __init__(self, class_expressions: List[OWLClassExpression], - annotations: Optional[Iterable['OWLAnnotation']] = None): - super().__init__(class_expressions=class_expressions, annotations=annotations) - - -class OWLNaryIndividualAxiom(OWLIndividualAxiom, OWLNaryAxiom[OWLIndividual], metaclass=ABCMeta): - """Represents an axiom that contains two or more operands that could also be represented with - multiple pairwise individual axioms.""" - __slots__ = '_individuals' - - _individuals: List[OWLIndividual] - - @abstractmethod - def __init__(self, individuals: List[OWLIndividual], - annotations: Optional[Iterable['OWLAnnotation']] = None): - self._individuals = [*individuals] - super().__init__(annotations=annotations) - - def individuals(self) -> Iterable[OWLIndividual]: - """Get the individuals. - - Returns: - Generator containing the individuals. - """ - yield from self._individuals - - def as_pairwise_axioms(self) -> Iterable['OWLNaryIndividualAxiom']: - if len(self._individuals) < 3: - yield self - else: - yield from map(type(self), combinations(self._individuals, 2)) - - def __eq__(self, other): - if type(other) is type(self): - return self._individuals == other._individuals and self._annotations == other._annotations - return NotImplemented - - def __hash__(self): - return hash((*self._individuals, *self._annotations)) - - def __repr__(self): - return f'{type(self).__name__}({self._individuals},{self._annotations})' - - -class OWLDifferentIndividualsAxiom(OWLNaryIndividualAxiom): - """Represents a DifferentIndividuals axiom in the OWL 2 Specification.""" - __slots__ = () - - def __init__(self, individuals: List[OWLIndividual], - annotations: Optional[Iterable['OWLAnnotation']] = None): - super().__init__(individuals=individuals, annotations=annotations) - - -class OWLSameIndividualAxiom(OWLNaryIndividualAxiom): - """Represents a SameIndividual axiom in the OWL 2 Specification.""" - __slots__ = () - - def __init__(self, individuals: List[OWLIndividual], - annotations: Optional[Iterable['OWLAnnotation']] = None): - super().__init__(individuals=individuals, annotations=annotations) - - -class OWLNaryPropertyAxiom(Generic[_P], OWLPropertyAxiom, OWLNaryAxiom[_P], metaclass=ABCMeta): - """Represents an axiom that contains two or more operands that could also be represented with - multiple pairwise property axioms.""" - __slots__ = '_properties' - - _properties: List[_P] - - @abstractmethod - def __init__(self, properties: List[_P], annotations: Optional[Iterable['OWLAnnotation']] = None): - self._properties = [*properties] - super().__init__(annotations=annotations) - - def properties(self) -> Iterable[_P]: - """Get all the properties that appear in the axiom. - - Returns: - Generator containing the properties. - """ - yield from self._properties - - def as_pairwise_axioms(self) -> Iterable['OWLNaryPropertyAxiom']: - if len(self._properties) < 3: - yield self - else: - yield from map(type(self), combinations(self._properties, 2)) - - def __eq__(self, other): - if type(other) is type(self): - return self._properties == other._properties and self._annotations == other._annotations - return NotImplemented - - def __hash__(self): - return hash((*self._properties, *self._annotations)) - - def __repr__(self): - return f'{type(self).__name__}({self._properties},{self._annotations})' - - -class OWLEquivalentObjectPropertiesAxiom(OWLNaryPropertyAxiom[OWLObjectPropertyExpression], OWLObjectPropertyAxiom): - """Represents EquivalentObjectProperties axioms in the OWL 2 Specification.""" - __slots__ = () - - def __init__(self, properties: List[OWLObjectPropertyExpression], - annotations: Optional[Iterable['OWLAnnotation']] = None): - super().__init__(properties=properties, annotations=annotations) - - -class OWLDisjointObjectPropertiesAxiom(OWLNaryPropertyAxiom[OWLObjectPropertyExpression], OWLObjectPropertyAxiom): - """Represents DisjointObjectProperties axioms in the OWL 2 Specification.""" - __slots__ = () - - def __init__(self, properties: List[OWLObjectPropertyExpression], - annotations: Optional[Iterable['OWLAnnotation']] = None): - super().__init__(properties=properties, annotations=annotations) - - -class OWLInverseObjectPropertiesAxiom(OWLNaryPropertyAxiom[OWLObjectPropertyExpression], OWLObjectPropertyAxiom): - """Represents InverseObjectProperties axioms in the OWL 2 Specification.""" - __slots__ = '_first', '_second' - - _first: OWLObjectPropertyExpression - _second: OWLObjectPropertyExpression - - def __init__(self, first: OWLObjectPropertyExpression, second: OWLObjectPropertyExpression, - annotations: Optional[Iterable['OWLAnnotation']] = None): - self._first = first - self._second = second - super().__init__(properties=[first, second], annotations=annotations) - - def get_first_property(self) -> OWLObjectPropertyExpression: - return self._first - - def get_second_property(self) -> OWLObjectPropertyExpression: - return self._second - - def __repr__(self): - return f'OWLInverseObjectPropertiesAxiom(first={self._first},second={self._second},' \ - f'annotations={self._annotations})' - - -class OWLEquivalentDataPropertiesAxiom(OWLNaryPropertyAxiom[OWLDataPropertyExpression], OWLDataPropertyAxiom): - """Represents EquivalentDataProperties axioms in the OWL 2 Specification.""" - __slots__ = () - - def __init__(self, properties: List[OWLDataPropertyExpression], - annotations: Optional[Iterable['OWLAnnotation']] = None): - super().__init__(properties=properties, annotations=annotations) - - -class OWLDisjointDataPropertiesAxiom(OWLNaryPropertyAxiom[OWLDataPropertyExpression], OWLDataPropertyAxiom): - """Represents DisjointDataProperties axioms in the OWL 2 Specification.""" - __slots__ = () - - def __init__(self, properties: List[OWLDataPropertyExpression], - annotations: Optional[Iterable['OWLAnnotation']] = None): - super().__init__(properties=properties, annotations=annotations) - - -class OWLSubClassOfAxiom(OWLClassAxiom): - """Represents an SubClassOf axiom in the OWL 2 Specification.""" - __slots__ = '_sub_class', '_super_class' - - _sub_class: OWLClassExpression - _super_class: OWLClassExpression - - def __init__(self, sub_class: OWLClassExpression, super_class: OWLClassExpression, - annotations: Optional[Iterable['OWLAnnotation']] = None): - """Get an equivalent classes axiom with specified operands and no annotations. - - Args: - sub_class: The sub-class. - super_class: The super class. - annotations: Annotations. - """ - self._sub_class = sub_class - self._super_class = super_class - super().__init__(annotations=annotations) - - def get_sub_class(self) -> OWLClassExpression: - return self._sub_class - - def get_super_class(self) -> OWLClassExpression: - return self._super_class - - def __eq__(self, other): - if type(other) is type(self): - return self._super_class == other._super_class and self._sub_class == other._sub_class \ - and self._annotations == other._annotations - return NotImplemented - - def __hash__(self): - return hash((self._super_class, self._sub_class, *self._annotations)) - - def __repr__(self): - return f'OWLSubClassOfAxiom(sub_class={self._sub_class},super_class={self._super_class},' \ - f'annotations={self._annotations})' - - -class OWLDisjointUnionAxiom(OWLClassAxiom): - """Represents a DisjointUnion axiom in the OWL 2 Specification.""" - __slots__ = '_cls', '_class_expressions' - - _cls: OWLClass - _class_expressions: List[OWLClassExpression] - - def __init__(self, cls_: OWLClass, class_expressions: List[OWLClassExpression], - annotations: Optional[Iterable['OWLAnnotation']] = None): - self._cls = cls_ - self._class_expressions = class_expressions - super().__init__(annotations=annotations) - - def get_owl_class(self) -> OWLClass: - return self._cls - - def get_class_expressions(self) -> Iterable[OWLClassExpression]: - yield from self._class_expressions - - def get_owl_equivalent_classes_axiom(self) -> OWLEquivalentClassesAxiom: - return OWLEquivalentClassesAxiom(self._cls, OWLObjectUnionOf(self._class_expressions)) - - def get_owl_disjoint_classes_axiom(self) -> OWLDisjointClassesAxiom: - return OWLDisjointClassesAxiom(self._class_expressions) - - def __eq__(self, other): - if type(other) is type(self): - return self._cls == other._cls and self._class_expressions == other._class_expressions \ - and self._annotations == other._annotations - return NotImplemented - - def __hash__(self): - return hash((self._cls, *self._class_expressions, *self._annotations)) - - def __repr__(self): - return f'OWLDisjointUnionAxiom(class={self._cls},class_expressions={self._class_expressions},' \ - f'annotations={self._annotations})' - - -class OWLClassAssertionAxiom(OWLIndividualAxiom): - """Represents ClassAssertion axioms in the OWL 2 Specification.""" - __slots__ = '_individual', '_class_expression' - - _individual: OWLIndividual - _class_expression: OWLClassExpression - - def __init__(self, individual: OWLIndividual, class_expression: OWLClassExpression, - annotations: Optional[Iterable['OWLAnnotation']] = None): - """Get a ClassAssertion axiom for the specified individual and class expression. - Args: - individual: The individual. - class_expression: The class the individual belongs to. - annotations: Annotations. - """ - self._individual = individual - self._class_expression = class_expression - super().__init__(annotations=annotations) - - def get_individual(self) -> OWLIndividual: - return self._individual - - def get_class_expression(self) -> OWLClassExpression: - return self._class_expression - - def __eq__(self, other): - if type(other) is type(self): - return self._class_expression == other._class_expression and self._individual == other._individual \ - and self._annotations == other._annotations - return NotImplemented - - def __hash__(self): - return hash((self._individual, self._class_expression, *self._annotations)) - - def __repr__(self): - return f'OWLClassAssertionAxiom(individual={self._individual},class_expression={self._class_expression},' \ - f'annotations={self._annotations})' - - -class OWLAnnotationAxiom(OWLAxiom, metaclass=ABCMeta): - """A super interface for annotation axioms.""" - __slots__ = () - - def is_annotation_axiom(self) -> bool: - return True - - -class OWLAnnotationProperty(OWLProperty): - """Represents an AnnotationProperty in the OWL 2 specification.""" - __slots__ = '_iri' - - _iri: IRI - - def __init__(self, iri: IRI): - """Get a new OWLAnnotationProperty object. - - Args: - iri: New OWLAnnotationProperty IRI. - """ - self._iri = iri - - def get_iri(self) -> IRI: - # documented in parent - return self._iri - - -class OWLAnnotation(OWLObject): - """Annotations are used in the various types of annotation axioms, which bind annotations to their subjects - (i.e. axioms or declarations).""" - __slots__ = '_property', '_value' - - _property: OWLAnnotationProperty - _value: OWLAnnotationValue - - def __init__(self, property: OWLAnnotationProperty, value: OWLAnnotationValue): - """Gets an annotation. - - Args: - property: the annotation property. - value: The annotation value. - """ - self._property = property - self._value = value - - def get_property(self) -> OWLAnnotationProperty: - """Gets the property that this annotation acts along. - - Returns: - The annotation property. - """ - return self._property - - def get_value(self) -> OWLAnnotationValue: - """Gets the annotation value. The type of value will depend upon the type of the annotation e.g. whether the - annotation is an OWLLiteral, an IRI or an OWLAnonymousIndividual. - - Returns: - The annotation value. - """ - return self._value - - def __eq__(self, other): - if type(other) is type(self): - return self._property == other._property and self._value == other._value - return NotImplemented - - def __hash__(self): - return hash((self._property, self._value)) - - def __repr__(self): - return f'OWLAnnotation({self._property}, {self._value})' - - -class OWLAnnotationAssertionAxiom(OWLAnnotationAxiom): - """Represents AnnotationAssertion axioms in the OWL 2 specification.""" - __slots__ = '_subject', '_annotation' - - _subject: OWLAnnotationSubject - _annotation: OWLAnnotation - - def __init__(self, subject: OWLAnnotationSubject, annotation: OWLAnnotation): - """Get an annotation assertion axiom - with annotations. - - Args: - subject: Subject. - annotation: Annotation. - """ - assert isinstance(subject, OWLAnnotationSubject) - assert isinstance(annotation, OWLAnnotation) - - self._subject = subject - self._annotation = annotation - - def get_subject(self) -> OWLAnnotationSubject: - """Gets the subject of this object. - - Returns: - The subject. - """ - return self._subject - - def get_property(self) -> OWLAnnotationProperty: - """Gets the property. - - Returns: - The property. - """ - return self._annotation.get_property() - - def get_value(self) -> OWLAnnotationValue: - """Gets the annotation value. This is either an IRI, an OWLAnonymousIndividual or an OWLLiteral. - - Returns: - The annotation value. - """ - return self._annotation.get_value() - - def __eq__(self, other): - if type(other) is type(self): - return self._subject == other._subject and self._annotation == other._annotation - return NotImplemented - - def __hash__(self): - return hash((self._subject, self._annotation)) - - def __repr__(self): - return f'OWLAnnotationAssertionAxiom({self._subject}, {self._annotation})' - - -class OWLSubAnnotationPropertyOfAxiom(OWLAnnotationAxiom): - """Represents an SubAnnotationPropertyOf axiom in the OWL 2 specification.""" - __slots__ = '_sub_property', '_super_property' - - _sub_property: OWLAnnotationProperty - _super_property: OWLAnnotationProperty - - def __init__(self, sub_property: OWLAnnotationProperty, super_property: OWLAnnotationProperty, - annotations: Optional[Iterable['OWLAnnotation']] = None): - self._sub_property = sub_property - self._super_property = super_property - super().__init__(annotations=annotations) - - def get_sub_property(self) -> OWLAnnotationProperty: - return self._sub_property - - def get_super_property(self) -> OWLAnnotationProperty: - return self._super_property - - def __eq__(self, other): - if type(other) is type(self): - return self._sub_property == other._sub_property and self._super_property == other._super_property \ - and self._annotations == other._annotations - return NotImplemented - - def __hash__(self): - return hash((self._sub_property, self._super_property, *self._annotations)) - - def __repr__(self): - return f'OWLSubAnnotationPropertyOfAxiom(sub_property={self._sub_property},' \ - f'super_property={self._super_property},annotations={self._annotations})' - - -class OWLAnnotationPropertyDomainAxiom(OWLAnnotationAxiom): - """Represents an AnnotationPropertyDomain axiom in the OWL 2 specification.""" - __slots__ = '_property', '_domain' - - _property: OWLAnnotationProperty - _domain: IRI - - def __init__(self, property_: OWLAnnotationProperty, domain: IRI, - annotations: Optional[Iterable['OWLAnnotation']] = None): - self._property = property_ - self._domain = domain - super().__init__(annotations=annotations) - - def get_property(self) -> OWLAnnotationProperty: - return self._property - - def get_domain(self) -> IRI: - return self._domain - - def __eq__(self, other): - if type(other) is type(self): - return self._property == other._property and self._domain == other._domain \ - and self._annotations == other._annotations - return NotImplemented - - def __hash__(self): - return hash((self._property, self._domain, *self._annotations)) - - def __repr__(self): - return f'OWLAnnotationPropertyDomainAxiom({repr(self._property)},{repr(self._domain)},' \ - f'{repr(self._annotations)})' - - -class OWLAnnotationPropertyRangeAxiom(OWLAnnotationAxiom): - """Represents an AnnotationPropertyRange axiom in the OWL 2 specification.""" - __slots__ = '_property', '_range' - - _property: OWLAnnotationProperty - _range: IRI - - def __init__(self, property_: OWLAnnotationProperty, range_: IRI, - annotations: Optional[Iterable['OWLAnnotation']] = None): - self._property = property_ - self._range = range_ - super().__init__(annotations=annotations) - - def get_property(self) -> OWLAnnotationProperty: - return self._property - - def get_range(self) -> IRI: - return self._range - - def __eq__(self, other): - if type(other) is type(self): - return self._property == other._property and self._range == other._range \ - and self._annotations == other._annotations - return NotImplemented - - def __hash__(self): - return hash((self._property, self._range, *self._annotations)) - - def __repr__(self): - return f'OWLAnnotationPropertyRangeAxiom({repr(self._property)},{repr(self._range)},' \ - f'{repr(self._annotations)})' - - -class OWLSubPropertyAxiom(Generic[_P], OWLPropertyAxiom): - """ - Base interface for object and data sub-property axioms. - """ - __slots__ = '_sub_property', '_super_property' - - _sub_property: _P - _super_property: _P - - @abstractmethod - def __init__(self, sub_property: _P, super_property: _P, - annotations: Optional[Iterable['OWLAnnotation']] = None): - self._sub_property = sub_property - self._super_property = super_property - super().__init__(annotations=annotations) - - def get_sub_property(self) -> _P: - return self._sub_property - - def get_super_property(self) -> _P: - return self._super_property - - def __eq__(self, other): - if type(other) is type(self): - return self._sub_property == other._sub_property and self._super_property == other._super_property \ - and self._annotations == other._annotations - return NotImplemented - - def __hash__(self): - return hash((self._sub_property, self._super_property, *self._annotations)) - - def __repr__(self): - return f'{type(self).__name__}(sub_property={self._sub_property},super_property={self._super_property},' \ - f'annotations={self._annotations})' - - -class OWLSubObjectPropertyOfAxiom(OWLSubPropertyAxiom[OWLObjectPropertyExpression], OWLObjectPropertyAxiom): - """Represents a SubObjectPropertyOf axiom in the OWL 2 specification.""" - __slots__ = () - - def __init__(self, sub_property: OWLObjectPropertyExpression, super_property: OWLObjectPropertyExpression, - annotations: Optional[Iterable['OWLAnnotation']] = None): - super().__init__(sub_property=sub_property, super_property=super_property, annotations=annotations) +from abc import ABCMeta, abstractmethod +from itertools import combinations +from typing import Generic, Iterable, Sequence, Set, TypeVar, Union, Final, Optional, Protocol, ClassVar, List +from datetime import datetime, date +from pandas import Timedelta +from owlapy.vocab import OWLRDFVocabulary, XSDVocabulary, OWLFacet +from owlapy._utils import MOVE +from owlapy.owlobject import OWLObject, OWLEntity +from owlapy.owl_annotation import OWLAnnotationObject, OWLAnnotationSubject, OWLAnnotationValue +from owlapy.iri import IRI +from owlapy.has import HasIndex, HasIRI, HasOperands, HasFiller, HasCardinality +from owlapy.owl_class_expression import OWLNaryBooleanClassExpression, OWLClassExpression, OWLObjectComplementOf, \ + OWLAnonymousClassExpression, OWLBooleanClassExpression, OWLPropertyRange, OWLDataRange, OWLClass, OWLObjectUnionOf, \ + OWLObjectIntersectionOf +from owlapy.owl_property import OWLObjectPropertyExpression, OWLProperty, OWLPropertyExpression, \ + OWLDataPropertyExpression, OWLDataProperty, OWLObjectProperty +from owlapy.owl_restriction import (OWLRestriction, OWLObjectAllValuesFrom, OWLObjectSomeValuesFrom, + OWLQuantifiedRestriction, OWLQuantifiedObjectRestriction, + OWLObjectRestriction, OWLHasValueRestriction, OWLDataRestriction, + OWLCardinalityRestriction, OWLObjectMinCardinality, OWLObjectCardinalityRestriction,OWLDataAllValuesFrom, + OWLObjectHasSelf, OWLObjectMaxCardinality, OWLObjectExactCardinality,OWLDataExactCardinality) + +from owlapy.owl_individual import OWLNamedIndividual, OWLIndividual +from owlapy.owl_axiom import (OWLEquivalentClassesAxiom, OWLClassAxiom, + OWLDataPropertyDomainAxiom, OWLAxiom, OWLDataPropertyRangeAxiom, + OWLObjectPropertyDomainAxiom, OWLObjectPropertyRangeAxiom) +from owlapy.types import OWLDatatype +from owlapy.owl_data import OWLDataMinCardinality, OWLDataMaxCardinality,OWLDataComplementOf, OWLDataIntersectionOf, OWLDataHasValue, OWLDataOneOf, OWLDataSomeValuesFrom,OWLDataUnionOf +from owlapy.owl_data import OWLNaryDataRange, OWLQuantifiedDataRestriction, OWLDataCardinalityRestriction +from owlapy.owl_literal import OWLLiteral -class OWLSubDataPropertyOfAxiom(OWLSubPropertyAxiom[OWLDataPropertyExpression], OWLDataPropertyAxiom): - """Represents a SubDataPropertyOf axiom in the OWL 2 specification.""" - __slots__ = () +MOVE(OWLObject, OWLAnnotationObject, OWLAnnotationSubject, OWLAnnotationValue, HasIRI, IRI) - def __init__(self, sub_property: OWLDataPropertyExpression, super_property: OWLDataPropertyExpression, - annotations: Optional[Iterable['OWLAnnotation']] = None): - super().__init__(sub_property=sub_property, super_property=super_property, annotations=annotations) +_T = TypeVar('_T') #: +_C = TypeVar('_C', bound='OWLObject') #: +_P = TypeVar('_P', bound='OWLPropertyExpression') #: +_R = TypeVar('_R', bound='OWLPropertyRange') #: +Literals = Union['OWLLiteral', int, float, bool, Timedelta, datetime, date, str] #: +_M = TypeVar('_M', bound='OWLOntologyManager') #: -class OWLPropertyAssertionAxiom(Generic[_P, _C], OWLIndividualAxiom, metaclass=ABCMeta): - """Represents a PropertyAssertion axiom in the OWL 2 specification.""" - __slots__ = '_subject', '_property', '_object' +class OWLObjectHasValue(OWLHasValueRestriction[OWLIndividual], OWLObjectRestriction): + """Represents an ObjectHasValue class expression in the OWL 2 Specification.""" + __slots__ = '_property', '_v' + type_index: Final = 3007 - _subject: OWLIndividual - _property: _P - _object: _C + _property: OWLObjectPropertyExpression + _v: OWLIndividual - @abstractmethod - def __init__(self, subject: OWLIndividual, property_: _P, object_: _C, - annotations: Optional[Iterable['OWLAnnotation']] = None): - """Get a PropertyAssertion axiom for the specified subject, property, object. - Args: - subject: The subject of the property assertion. - property_: The property of the property assertion. - object_: The object of the property assertion. - annotations: Annotations. + def __init__(self, property: OWLObjectPropertyExpression, individual: OWLIndividual): """ - assert isinstance(subject, OWLIndividual) - - self._subject = subject - self._property = property_ - self._object = object_ - super().__init__(annotations=annotations) + Args: + property: The property that the restriction acts along. + individual: Individual for restriction. - def get_subject(self) -> OWLIndividual: - return self._subject + Returns: + A HasValue restriction with specified property and value + """ + super().__init__(individual) + self._property = property - def get_property(self) -> _P: + def get_property(self) -> OWLObjectPropertyExpression: + # documented in parent return self._property - def get_object(self) -> _C: - return self._object - - def __eq__(self, other): - if type(other) is type(self): - return self._subject == other._subject and self._property == other._property and \ - self._object == other._object and self._annotations == other._annotations - return NotImplemented + def as_some_values_from(self) -> OWLClassExpression: + """A convenience method that obtains this restriction as an existential restriction with a nominal filler. - def __hash__(self): - return hash((self._subject, self._property, self._object, *self._annotations)) + Returns: + The existential equivalent of this value restriction. simp(HasValue(p a)) = some(p {a}). + """ + return OWLObjectSomeValuesFrom(self.get_property(), OWLObjectOneOf(self.get_filler())) def __repr__(self): - return f'{type(self).__name__}(subject={self._subject},property={self._property},' \ - f'object={self._object},annotation={self._annotations})' - - -class OWLObjectPropertyAssertionAxiom(OWLPropertyAssertionAxiom[OWLObjectPropertyExpression, OWLIndividual]): - """Represents an ObjectPropertyAssertion axiom in the OWL 2 specification.""" - __slots__ = () - - def __init__(self, subject: OWLIndividual, property_: OWLObjectPropertyExpression, object_: OWLIndividual, - annotations: Optional[Iterable['OWLAnnotation']] = None): - super().__init__(subject, property_, object_, annotations) - - -class OWLNegativeObjectPropertyAssertionAxiom(OWLPropertyAssertionAxiom[OWLObjectPropertyExpression, OWLIndividual]): - """Represents a NegativeObjectPropertyAssertion axiom in the OWL 2 specification.""" - __slots__ = () - - def __init__(self, subject: OWLIndividual, property_: OWLObjectPropertyExpression, object_: OWLIndividual, - annotations: Optional[Iterable['OWLAnnotation']] = None): - super().__init__(subject, property_, object_, annotations) - - -class OWLDataPropertyAssertionAxiom(OWLPropertyAssertionAxiom[OWLDataPropertyExpression, OWLLiteral]): - """Represents an DataPropertyAssertion axiom in the OWL 2 specification.""" - __slots__ = () - - def __init__(self, subject: OWLIndividual, property_: OWLDataPropertyExpression, object_: OWLLiteral, - annotations: Optional[Iterable['OWLAnnotation']] = None): - super().__init__(subject, property_, object_, annotations) - - -class OWLNegativeDataPropertyAssertionAxiom(OWLPropertyAssertionAxiom[OWLDataPropertyExpression, OWLLiteral]): - """Represents an NegativeDataPropertyAssertion axiom in the OWL 2 specification.""" - __slots__ = () + return f'OWLObjectHasValue(property={self.get_property()}, individual={self._v})' - def __init__(self, subject: OWLIndividual, property_: OWLDataPropertyExpression, object_: OWLLiteral, - annotations: Optional[Iterable['OWLAnnotation']] = None): - super().__init__(subject, property_, object_, annotations) +class OWLObjectOneOf(OWLAnonymousClassExpression, HasOperands[OWLIndividual]): + """Represents an ObjectOneOf class expression in the OWL 2 Specification.""" + __slots__ = '_values' + type_index: Final = 3004 -class OWLUnaryPropertyAxiom(Generic[_P], OWLPropertyAxiom, metaclass=ABCMeta): - """Unary property axiom.""" - __slots__ = '_property' + def __init__(self, values: Union[OWLIndividual, Iterable[OWLIndividual]]): + if isinstance(values, OWLIndividual): + self._values = values, + else: + for _ in values: + assert isinstance(_, OWLIndividual) + self._values = tuple(values) - _property: _P + def individuals(self) -> Iterable[OWLIndividual]: + """Gets the individuals that are in the oneOf. These individuals represent the exact instances (extension) + of this class expression. - def __init__(self, property_: _P, annotations: Optional[Iterable[OWLAnnotation]] = None): - self._property = property_ - super().__init__(annotations=annotations) + Returns: + The individuals that are the values of this {@code ObjectOneOf} class expression. + """ + yield from self._values - def get_property(self) -> _P: - return self._property + def operands(self) -> Iterable[OWLIndividual]: + # documented in parent + yield from self.individuals() + def as_object_union_of(self) -> OWLClassExpression: + """Simplifies this enumeration to a union of singleton nominals. -class OWLObjectPropertyCharacteristicAxiom(OWLUnaryPropertyAxiom[OWLObjectPropertyExpression], - OWLObjectPropertyAxiom, metaclass=ABCMeta): - """Base interface for functional object property axiom.""" - __slots__ = () + Returns: + This enumeration in a more standard DL form. + simp({a}) = {a} simp({a0, ... , {an}) = unionOf({a0}, ... , {an}) + """ + if len(self._values) == 1: + return self + return OWLObjectUnionOf(map(lambda _: OWLObjectOneOf(_), self.individuals())) - @abstractmethod - def __init__(self, property_: OWLObjectPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): - super().__init__(property_=property_, annotations=annotations) + def __hash__(self): + return hash(self._values) def __eq__(self, other): - if type(other) is type(self): - return self._property == other._property and self._annotations == other._annotations + if type(other) == type(self): + return self._values == other._values return NotImplemented - def __hash__(self): - return hash((self._property, *self._annotations)) - def __repr__(self): - return f"{type(self).__name__}({repr(self._property)},{repr(self._annotations)})" - - -class OWLFunctionalObjectPropertyAxiom(OWLObjectPropertyCharacteristicAxiom): - """Represents FunctionalObjectProperty axioms in the OWL 2 specification.""" - __slots__ = () - - def __init__(self, property_: OWLObjectPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): - super().__init__(property_=property_, annotations=annotations) - - -class OWLAsymmetricObjectPropertyAxiom(OWLObjectPropertyCharacteristicAxiom): - """Represents AsymmetricObjectProperty axioms in the OWL 2 specification.""" - __slots__ = () - - def __init__(self, property_: OWLObjectPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): - super().__init__(property_=property_, annotations=annotations) - - -class OWLInverseFunctionalObjectPropertyAxiom(OWLObjectPropertyCharacteristicAxiom): - """Represents InverseFunctionalObjectProperty axioms in the OWL 2 specification.""" - __slots__ = () - - def __init__(self, property_: OWLObjectPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): - super().__init__(property_=property_, annotations=annotations) - - -class OWLIrreflexiveObjectPropertyAxiom(OWLObjectPropertyCharacteristicAxiom): - """Represents IrreflexiveObjectProperty axioms in the OWL 2 specification.""" - __slots__ = () + return f'OWLObjectOneOf({self._values})' - def __init__(self, property_: OWLObjectPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): - super().__init__(property_=property_, annotations=annotations) +class OWLOntologyID: + """An object that identifies an ontology. Since OWL 2, ontologies do not have to have an ontology IRI, or if they + have an ontology IRI then they can optionally also have a version IRI. Instances of this OWLOntologyID class bundle + identifying information of an ontology together. If an ontology doesn't have an ontology IRI then we say that it is + "anonymous". + """ + __slots__ = '_ontology_iri', '_version_iri' -class OWLReflexiveObjectPropertyAxiom(OWLObjectPropertyCharacteristicAxiom): - """Represents ReflexiveObjectProperty axioms in the OWL 2 specification.""" - __slots__ = () + _ontology_iri: Optional[IRI] + _version_iri: Optional[IRI] - def __init__(self, property_: OWLObjectPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): - super().__init__(property_=property_, annotations=annotations) + def __init__(self, ontology_iri: Optional[IRI] = None, version_iri: Optional[IRI] = None): + """Constructs an ontology identifier specifying the ontology IRI and version IRI. + Args: + ontology_iri: The ontology IRI (optional). + version_iri: The version IRI (must be None if no ontology_iri is provided). + """ + self._ontology_iri = ontology_iri + self._version_iri = version_iri -class OWLSymmetricObjectPropertyAxiom(OWLObjectPropertyCharacteristicAxiom): - """Represents SymmetricObjectProperty axioms in the OWL 2 specification.""" - __slots__ = () + def get_ontology_iri(self) -> Optional[IRI]: + """Gets the ontology IRI. - def __init__(self, property_: OWLObjectPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): - super().__init__(property_=property_, annotations=annotations) + Returns: + Ontology IRI. If the ontology is anonymous, it will return None. + """ + return self._ontology_iri + def get_version_iri(self) -> Optional[IRI]: + """Gets the version IRI. -class OWLTransitiveObjectPropertyAxiom(OWLObjectPropertyCharacteristicAxiom): - """Represents TransitiveObjectProperty axioms in the OWL 2 specification.""" - __slots__ = () + Returns: + Version IRI or None. + """ + return self._version_iri - def __init__(self, property_: OWLObjectPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): - super().__init__(property_=property_, annotations=annotations) + def get_default_document_iri(self) -> Optional[IRI]: + """Gets the IRI which is used as a default for the document that contain a representation of an ontology with + this ID. This will be the version IRI if there is an ontology IRI and version IRI, else it will be the ontology + IRI if there is an ontology IRI but no version IRI, else it will be None if there is no ontology IRI. See + Ontology Documents in the OWL 2 Structural Specification. + Returns: + the IRI that can be used as a default for an ontology document, or None. + """ + if self._ontology_iri is not None: + if self._version_iri is not None: + return self._version_iri + return self._ontology_iri -class OWLDataPropertyCharacteristicAxiom(OWLUnaryPropertyAxiom[OWLDataPropertyExpression], - OWLDataPropertyAxiom, metaclass=ABCMeta): - """Base interface for Functional data property axiom.""" - __slots__ = () + def is_anonymous(self) -> bool: + return self._ontology_iri is None - @abstractmethod - def __init__(self, property_: OWLDataPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): - super().__init__(property_=property_, annotations=annotations) + def __repr__(self): + return f"OWLOntologyID({repr(self._ontology_iri)}, {repr(self._version_iri)})" def __eq__(self, other): if type(other) is type(self): - return self._property == other._property and self._annotations == other._annotations + return self._ontology_iri == other._ontology_iri and self._version_iri == other._version_iri return NotImplemented - def __hash__(self): - return hash((self._property, *self._annotations)) - - def __repr__(self): - return f"{type(self).__name__}({repr(self._property)},{repr(self._annotations)})" - -class OWLFunctionalDataPropertyAxiom(OWLDataPropertyCharacteristicAxiom): - """Represents FunctionalDataProperty axioms in the OWL 2 specification.""" - __slots__ = () - - def __init__(self, property_: OWLDataPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): - super().__init__(property_=property_, annotations=annotations) +class OWLDatatypeRestriction(OWLDataRange): + """Represents a DatatypeRestriction data range in the OWL 2 Specification.""" + __slots__ = '_type', '_facet_restrictions' + type_index: Final = 4006 -class OWLPropertyDomainAxiom(Generic[_P], OWLUnaryPropertyAxiom[_P], metaclass=ABCMeta): - """Represents ObjectPropertyDomain axioms in the OWL 2 specification.""" - __slots__ = '_domain' + _type: OWLDatatype + _facet_restrictions: Sequence['OWLFacetRestriction'] - _domain: OWLClassExpression + def __init__(self, type_: OWLDatatype, facet_restrictions: Union['OWLFacetRestriction', + Iterable['OWLFacetRestriction']]): + self._type = type_ + if isinstance(facet_restrictions, OWLFacetRestriction): + facet_restrictions = facet_restrictions, + self._facet_restrictions = tuple(facet_restrictions) - @abstractmethod - def __init__(self, property_: _P, domain: OWLClassExpression, - annotations: Optional[Iterable[OWLAnnotation]] = None): - self._domain = domain - super().__init__(property_=property_, annotations=annotations) + def get_datatype(self) -> OWLDatatype: + return self._type - def get_domain(self) -> OWLClassExpression: - return self._domain + def get_facet_restrictions(self) -> Sequence['OWLFacetRestriction']: + return self._facet_restrictions def __eq__(self, other): if type(other) is type(self): - return self._property == other._property and self._domain == other._domain \ - and self._annotations == other._annotations + return self._type == other._type \ + and self._facet_restrictions == other._facet_restrictions return NotImplemented def __hash__(self): - return hash((self._property, self._domain, *self._annotations)) + return hash((self._type, self._facet_restrictions)) def __repr__(self): - return f"{type(self).__name__}({repr(self._property)},{repr(self._domain)},{repr(self._annotations)})" + return f'OWLDatatypeRestriction({repr(self._type)}, {repr(self._facet_restrictions)})' -class OWLPropertyRangeAxiom(Generic[_P, _R], OWLUnaryPropertyAxiom[_P], metaclass=ABCMeta): - """Represents ObjectPropertyRange axioms in the OWL 2 specification.""" - __slots__ = '_range' +class OWLFacetRestriction(OWLObject): + """A facet restriction is used to restrict a particular datatype.""" - _range: _R + __slots__ = '_facet', '_literal' - @abstractmethod - def __init__(self, property_: _P, range_: _R, annotations: Optional[Iterable[OWLAnnotation]] = None): - self._range = range_ - super().__init__(property_=property_, annotations=annotations) + type_index: Final = 4007 - def get_range(self) -> _R: - return self._range + _facet: OWLFacet + _literal: 'OWLLiteral' + + def __init__(self, facet: OWLFacet, literal: Literals): + self._facet = facet + if isinstance(literal, OWLLiteral): + self._literal = literal + else: + self._literal = OWLLiteral(literal) + + def get_facet(self) -> OWLFacet: + return self._facet + + def get_facet_value(self) -> 'OWLLiteral': + return self._literal def __eq__(self, other): if type(other) is type(self): - return self._property == other._property and self._range == other._range \ - and self._annotations == other._annotations + return self._facet == other._facet and self._literal == other._literal return NotImplemented def __hash__(self): - return hash((self._property, self._range, *self._annotations)) + return hash((self._facet, self._literal)) def __repr__(self): - return f"{type(self).__name__}({repr(self._property)},{repr(self._range)},{repr(self._annotations)})" - - -class OWLObjectPropertyDomainAxiom(OWLPropertyDomainAxiom[OWLObjectPropertyExpression]): - """ Represents a ObjectPropertyDomain axiom in the OWL 2 Specification.""" - __slots__ = () - - def __init__(self, property_: OWLObjectPropertyExpression, domain: OWLClassExpression, - annotations: Optional[Iterable[OWLAnnotation]] = None): - super().__init__(property_=property_, domain=domain, annotations=annotations) - - -class OWLDataPropertyDomainAxiom(OWLPropertyDomainAxiom[OWLDataPropertyExpression]): - """ Represents a DataPropertyDomain axiom in the OWL 2 Specification.""" - __slots__ = () - - def __init__(self, property_: OWLDataPropertyExpression, domain: OWLClassExpression, - annotations: Optional[Iterable[OWLAnnotation]] = None): - super().__init__(property_=property_, domain=domain, annotations=annotations) + return f'OWLFacetRestriction({self._facet}, {repr(self._literal)})' -class OWLObjectPropertyRangeAxiom(OWLPropertyRangeAxiom[OWLObjectPropertyExpression, OWLClassExpression]): - """ Represents a ObjectPropertyRange axiom in the OWL 2 Specification.""" - __slots__ = () +class OWLImportsDeclaration(HasIRI): + """Represents an import statement in an ontology.""" + __slots__ = '_iri' - def __init__(self, property_: OWLObjectPropertyExpression, range_: OWLClassExpression, - annotations: Optional[Iterable[OWLAnnotation]] = None): - super().__init__(property_=property_, range_=range_, annotations=annotations) + def __init__(self, import_iri: IRI): + """ + Args: + import_import_iri: Imported ontology. + Returns: + An imports declaration. + """ + self._iri = import_iri -class OWLDataPropertyRangeAxiom(OWLPropertyRangeAxiom[OWLDataPropertyExpression, OWLDataRange]): - """ Represents a DataPropertyRange axiom in the OWL 2 Specification.""" - __slots__ = () + def get_iri(self) -> IRI: + """Gets the import IRI. - def __init__(self, property_: OWLDataPropertyExpression, range_: OWLDataRange, - annotations: Optional[Iterable[OWLAnnotation]] = None): - super().__init__(property_=property_, range_=range_, annotations=annotations) + Returns: + The import IRI that points to the ontology to be imported. The imported ontology might have this IRI as + its ontology IRI but this is not mandated. For example, an ontology with a non-resolvable ontology IRI + can be deployed at a resolvable URL. + """ + return self._iri class OWLOntology(OWLObject, metaclass=ABCMeta): @@ -2918,7 +924,7 @@ class expression with respect to the imports closure of the root ontology. """Important constant objects section""" - +# @TODO: Some of them must be removed from here as they are defined under owl literal OWLThing: Final = OWLClass(OWLRDFVocabulary.OWL_THING.get_iri()) #: : :The OWL Class corresponding to owl:Thing OWLNothing: Final = OWLClass(OWLRDFVocabulary.OWL_NOTHING.get_iri()) #: : :The OWL Class corresponding to owl:Nothing #: the built in top object property diff --git a/owlapy/owl_annotation.py b/owlapy/owl_annotation.py index e9942de4..870b855a 100644 --- a/owlapy/owl_annotation.py +++ b/owlapy/owl_annotation.py @@ -2,6 +2,7 @@ from .owlobject import OWLObject from typing import Optional + class OWLAnnotationObject(OWLObject, metaclass=ABCMeta): """A marker interface for the values (objects) of annotations.""" __slots__ = () @@ -44,4 +45,4 @@ def as_literal(self) -> Optional['OWLLiteral']: Returns: if the value is a literal, returns it. Return None otherwise """ - return None + return None \ No newline at end of file diff --git a/owlapy/owl_axiom.py b/owlapy/owl_axiom.py new file mode 100644 index 00000000..5fa558ed --- /dev/null +++ b/owlapy/owl_axiom.py @@ -0,0 +1,1097 @@ +from abc import ABCMeta, abstractmethod + +from typing import TypeVar, List, Optional, Iterable, Generic, Final +from .owl_property import OWLDataPropertyExpression, OWLObjectPropertyExpression +from .owlobject import OWLObject, OWLEntity +from .types import OWLDatatype, OWLDataRange +from .has import HasOperands +from .owl_property import OWLPropertyExpression, OWLProperty +from .owl_class_expression import OWLClassExpression, OWLClass +from .owl_individual import OWLIndividual +from .iri import IRI +from owlapy.owl_annotation import OWLAnnotationSubject, OWLAnnotationValue +from .owl_literal import OWLLiteral + +_C = TypeVar('_C', bound='OWLObject') #: +_P = TypeVar('_P', bound='OWLPropertyExpression') #: +_R = TypeVar('_R', bound='OWLPropertyRange') #: + +class OWLAxiom(OWLObject, metaclass=ABCMeta): + """Represents Axioms in the OWL 2 Specification. + + An OWL ontology contains a set of axioms. These axioms can be annotation axioms, declaration axioms, imports axioms + or logical axioms. + """ + __slots__ = '_annotations' + + _annotations: List['OWLAnnotation'] + + def __init__(self, annotations: Optional[Iterable['OWLAnnotation']] = None): + self._annotations = list(annotations) if annotations is not None else list() + + def annotations(self) -> Optional[List['OWLAnnotation']]: + return self._annotations + + def is_annotated(self) -> bool: + return self._annotations is not None and len(self._annotations) > 0 + + def is_logical_axiom(self) -> bool: + return False + + def is_annotation_axiom(self) -> bool: + return False + # TODO: XXX + + +class OWLLogicalAxiom(OWLAxiom, metaclass=ABCMeta): + """A base interface of all axioms that affect the logical meaning of an ontology. This excludes declaration axioms + (including imports declarations) and annotation axioms. + """ + __slots__ = () + + def __init__(self, annotations: Optional[Iterable['OWLAnnotation']] = None): + super().__init__(annotations=annotations) + + def is_logical_axiom(self) -> bool: + return True + + +class OWLPropertyAxiom(OWLLogicalAxiom, metaclass=ABCMeta): + """The base interface for property axioms.""" + __slots__ = () + + def __init__(self, annotations: Optional[Iterable['OWLAnnotation']] = None): + super().__init__(annotations=annotations) + + +class OWLObjectPropertyAxiom(OWLPropertyAxiom, metaclass=ABCMeta): + """The base interface for object property axioms.""" + __slots__ = () + + +class OWLDataPropertyAxiom(OWLPropertyAxiom, metaclass=ABCMeta): + """The base interface for data property axioms.""" + __slots__ = () + + +class OWLIndividualAxiom(OWLLogicalAxiom, metaclass=ABCMeta): + """The base interface for individual axioms.""" + __slots__ = () + + def __init__(self, annotations: Optional[Iterable['OWLAnnotation']] = None): + super().__init__(annotations=annotations) + + +class OWLClassAxiom(OWLLogicalAxiom, metaclass=ABCMeta): + """The base interface for class axioms.""" + __slots__ = () + + def __init__(self, annotations: Optional[Iterable['OWLAnnotation']] = None): + super().__init__(annotations=annotations) + + +class OWLDeclarationAxiom(OWLAxiom): + """Represents a Declaration axiom in the OWL 2 Specification. A declaration axiom declares an entity in an ontology. + It doesn't affect the logical meaning of the ontology.""" + __slots__ = '_entity' + + _entity: OWLEntity + + def __init__(self, entity: OWLEntity, annotations: Optional[Iterable['OWLAnnotation']] = None): + self._entity = entity + super().__init__(annotations=annotations) + + def get_entity(self) -> OWLEntity: + return self._entity + + def __eq__(self, other): + if type(other) is type(self): + return self._entity == other._entity and self._annotations == other._annotations + return NotImplemented + + def __hash__(self): + return hash((self._entity, *self._annotations)) + + def __repr__(self): + return f'OWLDeclarationAxiom(entity={self._entity},annotations={self._annotations})' + + +class OWLDatatypeDefinitionAxiom(OWLLogicalAxiom): + """Represents a DatatypeDefinition axiom in the OWL 2 Specification.""" + __slots__ = '_datatype', '_datarange' + + _datatype: OWLDatatype + _datarange: OWLDataRange + + def __init__(self, datatype: OWLDatatype, datarange: OWLDataRange, + annotations: Optional[Iterable['OWLAnnotation']] = None): + self._datatype = datatype + self._datarange = datarange + super().__init__(annotations=annotations) + + def get_datatype(self) -> OWLDatatype: + return self._datatype + + def get_datarange(self) -> OWLDataRange: + return self._datarange + + def __eq__(self, other): + if type(other) is type(self): + return self._datatype == other._datatype and self._datarange == other._datarange \ + and self._annotations == other._annotations + return NotImplemented + + def __hash__(self): + return hash((self._datatype, self._datarange, *self._annotations)) + + def __repr__(self): + return f'OWLDatatypeDefinitionAxiom(datatype={self._datatype},datarange={self._datarange},' \ + f'annotations={self._annotations})' + + +class OWLHasKeyAxiom(OWLLogicalAxiom, HasOperands[OWLPropertyExpression]): + """Represents a HasKey axiom in the OWL 2 Specification.""" + __slots__ = '_class_expression', '_property_expressions' + + _class_expression: OWLClassExpression + _property_expressions: List[OWLPropertyExpression] + + def __init__(self, class_expression: OWLClassExpression, property_expressions: List[OWLPropertyExpression], + annotations: Optional[Iterable['OWLAnnotation']] = None): + self._class_expression = class_expression + self._property_expressions = property_expressions + super().__init__(annotations=annotations) + + def get_class_expression(self) -> OWLClassExpression: + return self._class_expression + + def get_property_expressions(self) -> List[OWLPropertyExpression]: + return self._property_expressions + + def operands(self) -> Iterable[OWLPropertyExpression]: + yield from self._property_expressions + + def __eq__(self, other): + if type(other) is type(self): + return self._class_expression == other._class_expression \ + and self._property_expressions == other._property_expressions \ + and self._annotations == other._annotations + return NotImplemented + + def __hash__(self): + return hash((self._class_expression, *self._property_expressions, *self._annotations)) + + def __repr__(self): + return f'OWLHasKeyAxiom(class_expression={self._class_expression},' \ + f'property_expressions={self._property_expressions},annotations={self._annotations})' + + +class OWLNaryAxiom(Generic[_C], OWLAxiom, metaclass=ABCMeta): + """Represents an axiom that contains two or more operands that could also be represented with multiple pairwise + axioms. + + Args: + _C: Class of contained objects. + """ + __slots__ = () + + @abstractmethod + def as_pairwise_axioms(self) -> Iterable['OWLNaryAxiom[_C]']: + pass + + +# noinspection PyUnresolvedReferences +# noinspection PyDunderSlots +class OWLNaryClassAxiom(OWLClassAxiom, OWLNaryAxiom[OWLClassExpression], metaclass=ABCMeta): + """Represents an axiom that contains two or more operands that could also be represented with + multiple pairwise axioms.""" + __slots__ = '_class_expressions' + _class_expressions: List[OWLClassExpression] + + @abstractmethod + def __init__(self, class_expressions: List[OWLClassExpression], + annotations: Optional[Iterable['OWLAnnotation']] = None): + self._class_expressions = [*class_expressions] + super().__init__(annotations=annotations) + + def class_expressions(self) -> Iterable[OWLClassExpression]: + """Gets all of the top level class expressions that appear in this axiom. + + Returns: + Sorted stream of class expressions that appear in the axiom. + """ + yield from self._class_expressions + + def as_pairwise_axioms(self) -> Iterable['OWLNaryClassAxiom']: + """Gets this axiom as a set of pairwise axioms; if the axiom contains only two operands, + the axiom itself is returned unchanged, including its annotations. + + Returns: + This axiom as a set of pairwise axioms. + """ + if len(self._class_expressions) < 3: + yield self + else: + yield from map(type(self), combinations(self._class_expressions, 2)) + + def __eq__(self, other): + if type(other) is type(self): + return self._class_expressions == other._class_expressions and self._annotations == other._annotations + return NotImplemented + + def __hash__(self): + return hash((*self._class_expressions, *self._annotations)) + + def __repr__(self): + return f'{type(self).__name__}({self._class_expressions},{self._annotations})' + + +class OWLEquivalentClassesAxiom(OWLNaryClassAxiom): + """Represents an EquivalentClasses axiom in the OWL 2 Specification.""" + __slots__ = () + + def __init__(self, class_expressions: List[OWLClassExpression], + annotations: Optional[Iterable['OWLAnnotation']] = None): + super().__init__(class_expressions=class_expressions, annotations=annotations) + + def contains_named_equivalent_class(self) -> bool: + return any(isinstance(ce, OWLClass) for ce in self._class_expressions) + + def contains_owl_nothing(self) -> bool: + return any(isinstance(ce, OWLNothing) for ce in self._class_expressions) + + def contains_owl_thing(self) -> bool: + return any(isinstance(ce, OWLThing) for ce in self._class_expressions) + + def named_classes(self) -> Iterable[OWLClass]: + yield from (ce for ce in self._class_expressions if isinstance(ce, OWLClass)) + + +class OWLDisjointClassesAxiom(OWLNaryClassAxiom): + """Represents a DisjointClasses axiom in the OWL 2 Specification.""" + __slots__ = () + + def __init__(self, class_expressions: List[OWLClassExpression], + annotations: Optional[Iterable['OWLAnnotation']] = None): + super().__init__(class_expressions=class_expressions, annotations=annotations) + + +class OWLNaryIndividualAxiom(OWLIndividualAxiom, OWLNaryAxiom[OWLIndividual], metaclass=ABCMeta): + """Represents an axiom that contains two or more operands that could also be represented with + multiple pairwise individual axioms.""" + __slots__ = '_individuals' + + _individuals: List[OWLIndividual] + + @abstractmethod + def __init__(self, individuals: List[OWLIndividual], + annotations: Optional[Iterable['OWLAnnotation']] = None): + self._individuals = [*individuals] + super().__init__(annotations=annotations) + + def individuals(self) -> Iterable[OWLIndividual]: + """Get the individuals. + + Returns: + Generator containing the individuals. + """ + yield from self._individuals + + def as_pairwise_axioms(self) -> Iterable['OWLNaryIndividualAxiom']: + if len(self._individuals) < 3: + yield self + else: + yield from map(type(self), combinations(self._individuals, 2)) + + def __eq__(self, other): + if type(other) is type(self): + return self._individuals == other._individuals and self._annotations == other._annotations + return NotImplemented + + def __hash__(self): + return hash((*self._individuals, *self._annotations)) + + def __repr__(self): + return f'{type(self).__name__}({self._individuals},{self._annotations})' + + +class OWLDifferentIndividualsAxiom(OWLNaryIndividualAxiom): + """Represents a DifferentIndividuals axiom in the OWL 2 Specification.""" + __slots__ = () + + def __init__(self, individuals: List[OWLIndividual], + annotations: Optional[Iterable['OWLAnnotation']] = None): + super().__init__(individuals=individuals, annotations=annotations) + + +class OWLSameIndividualAxiom(OWLNaryIndividualAxiom): + """Represents a SameIndividual axiom in the OWL 2 Specification.""" + __slots__ = () + + def __init__(self, individuals: List[OWLIndividual], + annotations: Optional[Iterable['OWLAnnotation']] = None): + super().__init__(individuals=individuals, annotations=annotations) + + +class OWLNaryPropertyAxiom(Generic[_P], OWLPropertyAxiom, OWLNaryAxiom[_P], metaclass=ABCMeta): + """Represents an axiom that contains two or more operands that could also be represented with + multiple pairwise property axioms.""" + __slots__ = '_properties' + + _properties: List[_P] + + @abstractmethod + def __init__(self, properties: List[_P], annotations: Optional[Iterable['OWLAnnotation']] = None): + self._properties = [*properties] + super().__init__(annotations=annotations) + + def properties(self) -> Iterable[_P]: + """Get all the properties that appear in the axiom. + + Returns: + Generator containing the properties. + """ + yield from self._properties + + def as_pairwise_axioms(self) -> Iterable['OWLNaryPropertyAxiom']: + if len(self._properties) < 3: + yield self + else: + yield from map(type(self), combinations(self._properties, 2)) + + def __eq__(self, other): + if type(other) is type(self): + return self._properties == other._properties and self._annotations == other._annotations + return NotImplemented + + def __hash__(self): + return hash((*self._properties, *self._annotations)) + + def __repr__(self): + return f'{type(self).__name__}({self._properties},{self._annotations})' + + +class OWLEquivalentObjectPropertiesAxiom(OWLNaryPropertyAxiom[OWLObjectPropertyExpression], OWLObjectPropertyAxiom): + """Represents EquivalentObjectProperties axioms in the OWL 2 Specification.""" + __slots__ = () + + def __init__(self, properties: List[OWLObjectPropertyExpression], + annotations: Optional[Iterable['OWLAnnotation']] = None): + super().__init__(properties=properties, annotations=annotations) + + +class OWLDisjointObjectPropertiesAxiom(OWLNaryPropertyAxiom[OWLObjectPropertyExpression], OWLObjectPropertyAxiom): + """Represents DisjointObjectProperties axioms in the OWL 2 Specification.""" + __slots__ = () + + def __init__(self, properties: List[OWLObjectPropertyExpression], + annotations: Optional[Iterable['OWLAnnotation']] = None): + super().__init__(properties=properties, annotations=annotations) + + +class OWLInverseObjectPropertiesAxiom(OWLNaryPropertyAxiom[OWLObjectPropertyExpression], OWLObjectPropertyAxiom): + """Represents InverseObjectProperties axioms in the OWL 2 Specification.""" + __slots__ = '_first', '_second' + + _first: OWLObjectPropertyExpression + _second: OWLObjectPropertyExpression + + def __init__(self, first: OWLObjectPropertyExpression, second: OWLObjectPropertyExpression, + annotations: Optional[Iterable['OWLAnnotation']] = None): + self._first = first + self._second = second + super().__init__(properties=[first, second], annotations=annotations) + + def get_first_property(self) -> OWLObjectPropertyExpression: + return self._first + + def get_second_property(self) -> OWLObjectPropertyExpression: + return self._second + + def __repr__(self): + return f'OWLInverseObjectPropertiesAxiom(first={self._first},second={self._second},' \ + f'annotations={self._annotations})' + + +class OWLEquivalentDataPropertiesAxiom(OWLNaryPropertyAxiom[OWLDataPropertyExpression], OWLDataPropertyAxiom): + """Represents EquivalentDataProperties axioms in the OWL 2 Specification.""" + __slots__ = () + + def __init__(self, properties: List[OWLDataPropertyExpression], + annotations: Optional[Iterable['OWLAnnotation']] = None): + super().__init__(properties=properties, annotations=annotations) + + +class OWLDisjointDataPropertiesAxiom(OWLNaryPropertyAxiom[OWLDataPropertyExpression], OWLDataPropertyAxiom): + """Represents DisjointDataProperties axioms in the OWL 2 Specification.""" + __slots__ = () + + def __init__(self, properties: List[OWLDataPropertyExpression], + annotations: Optional[Iterable['OWLAnnotation']] = None): + super().__init__(properties=properties, annotations=annotations) + + +class OWLSubClassOfAxiom(OWLClassAxiom): + """Represents an SubClassOf axiom in the OWL 2 Specification.""" + __slots__ = '_sub_class', '_super_class' + + _sub_class: OWLClassExpression + _super_class: OWLClassExpression + + def __init__(self, sub_class: OWLClassExpression, super_class: OWLClassExpression, + annotations: Optional[Iterable['OWLAnnotation']] = None): + """Get an equivalent classes axiom with specified operands and no annotations. + + Args: + sub_class: The sub-class. + super_class: The super class. + annotations: Annotations. + """ + self._sub_class = sub_class + self._super_class = super_class + super().__init__(annotations=annotations) + + def get_sub_class(self) -> OWLClassExpression: + return self._sub_class + + def get_super_class(self) -> OWLClassExpression: + return self._super_class + + def __eq__(self, other): + if type(other) is type(self): + return self._super_class == other._super_class and self._sub_class == other._sub_class \ + and self._annotations == other._annotations + return NotImplemented + + def __hash__(self): + return hash((self._super_class, self._sub_class, *self._annotations)) + + def __repr__(self): + return f'OWLSubClassOfAxiom(sub_class={self._sub_class},super_class={self._super_class},' \ + f'annotations={self._annotations})' + + +class OWLDisjointUnionAxiom(OWLClassAxiom): + """Represents a DisjointUnion axiom in the OWL 2 Specification.""" + __slots__ = '_cls', '_class_expressions' + + _cls: OWLClass + _class_expressions: List[OWLClassExpression] + + def __init__(self, cls_: OWLClass, class_expressions: List[OWLClassExpression], + annotations: Optional[Iterable['OWLAnnotation']] = None): + self._cls = cls_ + self._class_expressions = class_expressions + super().__init__(annotations=annotations) + + def get_owl_class(self) -> OWLClass: + return self._cls + + def get_class_expressions(self) -> Iterable[OWLClassExpression]: + yield from self._class_expressions + + def get_owl_equivalent_classes_axiom(self) -> OWLEquivalentClassesAxiom: + return OWLEquivalentClassesAxiom(self._cls, OWLObjectUnionOf(self._class_expressions)) + + def get_owl_disjoint_classes_axiom(self) -> OWLDisjointClassesAxiom: + return OWLDisjointClassesAxiom(self._class_expressions) + + def __eq__(self, other): + if type(other) is type(self): + return self._cls == other._cls and self._class_expressions == other._class_expressions \ + and self._annotations == other._annotations + return NotImplemented + + def __hash__(self): + return hash((self._cls, *self._class_expressions, *self._annotations)) + + def __repr__(self): + return f'OWLDisjointUnionAxiom(class={self._cls},class_expressions={self._class_expressions},' \ + f'annotations={self._annotations})' + + +class OWLClassAssertionAxiom(OWLIndividualAxiom): + """Represents ClassAssertion axioms in the OWL 2 Specification.""" + __slots__ = '_individual', '_class_expression' + + _individual: OWLIndividual + _class_expression: OWLClassExpression + + def __init__(self, individual: OWLIndividual, class_expression: OWLClassExpression, + annotations: Optional[Iterable['OWLAnnotation']] = None): + """Get a ClassAssertion axiom for the specified individual and class expression. + Args: + individual: The individual. + class_expression: The class the individual belongs to. + annotations: Annotations. + """ + self._individual = individual + self._class_expression = class_expression + super().__init__(annotations=annotations) + + def get_individual(self) -> OWLIndividual: + return self._individual + + def get_class_expression(self) -> OWLClassExpression: + return self._class_expression + + def __eq__(self, other): + if type(other) is type(self): + return self._class_expression == other._class_expression and self._individual == other._individual \ + and self._annotations == other._annotations + return NotImplemented + + def __hash__(self): + return hash((self._individual, self._class_expression, *self._annotations)) + + def __repr__(self): + return f'OWLClassAssertionAxiom(individual={self._individual},class_expression={self._class_expression},' \ + f'annotations={self._annotations})' +class OWLAnnotationProperty(OWLProperty): + """Represents an AnnotationProperty in the OWL 2 specification.""" + __slots__ = '_iri' + + _iri: IRI + + def __init__(self, iri: IRI): + """Get a new OWLAnnotationProperty object. + + Args: + iri: New OWLAnnotationProperty IRI. + """ + self._iri = iri + + def get_iri(self) -> IRI: + # documented in parent + return self._iri + +class OWLAnnotation(OWLObject): + """Annotations are used in the various types of annotation axioms, which bind annotations to their subjects + (i.e. axioms or declarations).""" + __slots__ = '_property', '_value' + + _property: OWLAnnotationProperty + _value: OWLAnnotationValue + + def __init__(self, property: OWLAnnotationProperty, value: OWLAnnotationValue): + """Gets an annotation. + + Args: + property: the annotation property. + value: The annotation value. + """ + self._property = property + self._value = value + + def get_property(self) -> OWLAnnotationProperty: + """Gets the property that this annotation acts along. + + Returns: + The annotation property. + """ + return self._property + + def get_value(self) -> OWLAnnotationValue: + """Gets the annotation value. The type of value will depend upon the type of the annotation e.g. whether the + annotation is an OWLLiteral, an IRI or an OWLAnonymousIndividual. + + Returns: + The annotation value. + """ + return self._value + + def __eq__(self, other): + if type(other) is type(self): + return self._property == other._property and self._value == other._value + return NotImplemented + + def __hash__(self): + return hash((self._property, self._value)) + + def __repr__(self): + return f'OWLAnnotation({self._property}, {self._value})' +class OWLAnnotationAxiom(OWLAxiom, metaclass=ABCMeta): + """A super interface for annotation axioms.""" + __slots__ = () + + def is_annotation_axiom(self) -> bool: + return True +class OWLAnnotationAssertionAxiom(OWLAnnotationAxiom): + """Represents AnnotationAssertion axioms in the OWL 2 specification.""" + __slots__ = '_subject', '_annotation' + + _subject: OWLAnnotationSubject + _annotation: OWLAnnotation + + def __init__(self, subject: OWLAnnotationSubject, annotation: OWLAnnotation): + """Get an annotation assertion axiom - with annotations. + + Args: + subject: Subject. + annotation: Annotation. + """ + assert isinstance(subject, OWLAnnotationSubject) + assert isinstance(annotation, OWLAnnotation) + + self._subject = subject + self._annotation = annotation + + def get_subject(self) -> OWLAnnotationSubject: + """Gets the subject of this object. + + Returns: + The subject. + """ + return self._subject + + def get_property(self) -> OWLAnnotationProperty: + """Gets the property. + + Returns: + The property. + """ + return self._annotation.get_property() + + def get_value(self) -> OWLAnnotationValue: + """Gets the annotation value. This is either an IRI, an OWLAnonymousIndividual or an OWLLiteral. + + Returns: + The annotation value. + """ + return self._annotation.get_value() + + def __eq__(self, other): + if type(other) is type(self): + return self._subject == other._subject and self._annotation == other._annotation + return NotImplemented + + def __hash__(self): + return hash((self._subject, self._annotation)) + + def __repr__(self): + return f'OWLAnnotationAssertionAxiom({self._subject}, {self._annotation})' +class OWLSubAnnotationPropertyOfAxiom(OWLAnnotationAxiom): + """Represents an SubAnnotationPropertyOf axiom in the OWL 2 specification.""" + __slots__ = '_sub_property', '_super_property' + + _sub_property: OWLAnnotationProperty + _super_property: OWLAnnotationProperty + + def __init__(self, sub_property: OWLAnnotationProperty, super_property: OWLAnnotationProperty, + annotations: Optional[Iterable['OWLAnnotation']] = None): + self._sub_property = sub_property + self._super_property = super_property + super().__init__(annotations=annotations) + + def get_sub_property(self) -> OWLAnnotationProperty: + return self._sub_property + + def get_super_property(self) -> OWLAnnotationProperty: + return self._super_property + + def __eq__(self, other): + if type(other) is type(self): + return self._sub_property == other._sub_property and self._super_property == other._super_property \ + and self._annotations == other._annotations + return NotImplemented + + def __hash__(self): + return hash((self._sub_property, self._super_property, *self._annotations)) + + def __repr__(self): + return f'OWLSubAnnotationPropertyOfAxiom(sub_property={self._sub_property},' \ + f'super_property={self._super_property},annotations={self._annotations})' +class OWLAnnotationPropertyDomainAxiom(OWLAnnotationAxiom): + """Represents an AnnotationPropertyDomain axiom in the OWL 2 specification.""" + __slots__ = '_property', '_domain' + + _property: OWLAnnotationProperty + _domain: IRI + + def __init__(self, property_: OWLAnnotationProperty, domain: IRI, + annotations: Optional[Iterable['OWLAnnotation']] = None): + self._property = property_ + self._domain = domain + super().__init__(annotations=annotations) + + def get_property(self) -> OWLAnnotationProperty: + return self._property + + def get_domain(self) -> IRI: + return self._domain + + def __eq__(self, other): + if type(other) is type(self): + return self._property == other._property and self._domain == other._domain \ + and self._annotations == other._annotations + return NotImplemented + + def __hash__(self): + return hash((self._property, self._domain, *self._annotations)) + + def __repr__(self): + return f'OWLAnnotationPropertyDomainAxiom({repr(self._property)},{repr(self._domain)},' \ + f'{repr(self._annotations)})' +class OWLAnnotationPropertyRangeAxiom(OWLAnnotationAxiom): + """Represents an AnnotationPropertyRange axiom in the OWL 2 specification.""" + __slots__ = '_property', '_range' + + _property: OWLAnnotationProperty + _range: IRI + + def __init__(self, property_: OWLAnnotationProperty, range_: IRI, + annotations: Optional[Iterable['OWLAnnotation']] = None): + self._property = property_ + self._range = range_ + super().__init__(annotations=annotations) + + def get_property(self) -> OWLAnnotationProperty: + return self._property + + def get_range(self) -> IRI: + return self._range + + def __eq__(self, other): + if type(other) is type(self): + return self._property == other._property and self._range == other._range \ + and self._annotations == other._annotations + return NotImplemented + + def __hash__(self): + return hash((self._property, self._range, *self._annotations)) + + def __repr__(self): + return f'OWLAnnotationPropertyRangeAxiom({repr(self._property)},{repr(self._range)},' \ + f'{repr(self._annotations)})' +class OWLSubPropertyAxiom(Generic[_P], OWLPropertyAxiom): + """ + Base interface for object and data sub-property axioms. + """ + __slots__ = '_sub_property', '_super_property' + + _sub_property: _P + _super_property: _P + + @abstractmethod + def __init__(self, sub_property: _P, super_property: _P, + annotations: Optional[Iterable['OWLAnnotation']] = None): + self._sub_property = sub_property + self._super_property = super_property + super().__init__(annotations=annotations) + + def get_sub_property(self) -> _P: + return self._sub_property + + def get_super_property(self) -> _P: + return self._super_property + + def __eq__(self, other): + if type(other) is type(self): + return self._sub_property == other._sub_property and self._super_property == other._super_property \ + and self._annotations == other._annotations + return NotImplemented + + def __hash__(self): + return hash((self._sub_property, self._super_property, *self._annotations)) + + def __repr__(self): + return f'{type(self).__name__}(sub_property={self._sub_property},super_property={self._super_property},' \ + f'annotations={self._annotations})' +class OWLSubObjectPropertyOfAxiom(OWLSubPropertyAxiom[OWLObjectPropertyExpression], OWLObjectPropertyAxiom): + """Represents a SubObjectPropertyOf axiom in the OWL 2 specification.""" + __slots__ = () + + def __init__(self, sub_property: OWLObjectPropertyExpression, super_property: OWLObjectPropertyExpression, + annotations: Optional[Iterable['OWLAnnotation']] = None): + super().__init__(sub_property=sub_property, super_property=super_property, annotations=annotations) +class OWLSubDataPropertyOfAxiom(OWLSubPropertyAxiom[OWLDataPropertyExpression], OWLDataPropertyAxiom): + """Represents a SubDataPropertyOf axiom in the OWL 2 specification.""" + __slots__ = () + + def __init__(self, sub_property: OWLDataPropertyExpression, super_property: OWLDataPropertyExpression, + annotations: Optional[Iterable['OWLAnnotation']] = None): + super().__init__(sub_property=sub_property, super_property=super_property, annotations=annotations) + +class OWLPropertyAssertionAxiom(Generic[_P, _C], OWLIndividualAxiom, metaclass=ABCMeta): + """Represents a PropertyAssertion axiom in the OWL 2 specification.""" + __slots__ = '_subject', '_property', '_object' + + _subject: OWLIndividual + _property: _P + _object: _C + + @abstractmethod + def __init__(self, subject: OWLIndividual, property_: _P, object_: _C, + annotations: Optional[Iterable['OWLAnnotation']] = None): + """Get a PropertyAssertion axiom for the specified subject, property, object. + Args: + subject: The subject of the property assertion. + property_: The property of the property assertion. + object_: The object of the property assertion. + annotations: Annotations. + """ + assert isinstance(subject, OWLIndividual) + + self._subject = subject + self._property = property_ + self._object = object_ + super().__init__(annotations=annotations) + + def get_subject(self) -> OWLIndividual: + return self._subject + + def get_property(self) -> _P: + return self._property + + def get_object(self) -> _C: + return self._object + + def __eq__(self, other): + if type(other) is type(self): + return self._subject == other._subject and self._property == other._property and \ + self._object == other._object and self._annotations == other._annotations + return NotImplemented + + def __hash__(self): + return hash((self._subject, self._property, self._object, *self._annotations)) + + def __repr__(self): + return f'{type(self).__name__}(subject={self._subject},property={self._property},' \ + f'object={self._object},annotation={self._annotations})' +class OWLObjectPropertyAssertionAxiom(OWLPropertyAssertionAxiom[OWLObjectPropertyExpression, OWLIndividual]): + """Represents an ObjectPropertyAssertion axiom in the OWL 2 specification.""" + __slots__ = () + + def __init__(self, subject: OWLIndividual, property_: OWLObjectPropertyExpression, object_: OWLIndividual, + annotations: Optional[Iterable['OWLAnnotation']] = None): + super().__init__(subject, property_, object_, annotations) +class OWLNegativeObjectPropertyAssertionAxiom(OWLPropertyAssertionAxiom[OWLObjectPropertyExpression, OWLIndividual]): + """Represents a NegativeObjectPropertyAssertion axiom in the OWL 2 specification.""" + __slots__ = () + + def __init__(self, subject: OWLIndividual, property_: OWLObjectPropertyExpression, object_: OWLIndividual, + annotations: Optional[Iterable['OWLAnnotation']] = None): + super().__init__(subject, property_, object_, annotations) +class OWLDataPropertyAssertionAxiom(OWLPropertyAssertionAxiom[OWLDataPropertyExpression, OWLLiteral]): + """Represents an DataPropertyAssertion axiom in the OWL 2 specification.""" + __slots__ = () + + def __init__(self, subject: OWLIndividual, property_: OWLDataPropertyExpression, object_: OWLLiteral, + annotations: Optional[Iterable['OWLAnnotation']] = None): + super().__init__(subject, property_, object_, annotations) +class OWLNegativeDataPropertyAssertionAxiom(OWLPropertyAssertionAxiom[OWLDataPropertyExpression, OWLLiteral]): + """Represents an NegativeDataPropertyAssertion axiom in the OWL 2 specification.""" + __slots__ = () + + def __init__(self, subject: OWLIndividual, property_: OWLDataPropertyExpression, object_: OWLLiteral, + annotations: Optional[Iterable['OWLAnnotation']] = None): + super().__init__(subject, property_, object_, annotations) +class OWLUnaryPropertyAxiom(Generic[_P], OWLPropertyAxiom, metaclass=ABCMeta): + """Unary property axiom.""" + __slots__ = '_property' + + _property: _P + + def __init__(self, property_: _P, annotations: Optional[Iterable[OWLAnnotation]] = None): + self._property = property_ + super().__init__(annotations=annotations) + + def get_property(self) -> _P: + return self._property + + +class OWLObjectPropertyCharacteristicAxiom(OWLUnaryPropertyAxiom[OWLObjectPropertyExpression], + OWLObjectPropertyAxiom, metaclass=ABCMeta): + """Base interface for functional object property axiom.""" + __slots__ = () + + @abstractmethod + def __init__(self, property_: OWLObjectPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): + super().__init__(property_=property_, annotations=annotations) + + def __eq__(self, other): + if type(other) is type(self): + return self._property == other._property and self._annotations == other._annotations + return NotImplemented + + def __hash__(self): + return hash((self._property, *self._annotations)) + + def __repr__(self): + return f"{type(self).__name__}({repr(self._property)},{repr(self._annotations)})" + + +class OWLFunctionalObjectPropertyAxiom(OWLObjectPropertyCharacteristicAxiom): + """Represents FunctionalObjectProperty axioms in the OWL 2 specification.""" + __slots__ = () + + def __init__(self, property_: OWLObjectPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): + super().__init__(property_=property_, annotations=annotations) + + +class OWLAsymmetricObjectPropertyAxiom(OWLObjectPropertyCharacteristicAxiom): + """Represents AsymmetricObjectProperty axioms in the OWL 2 specification.""" + __slots__ = () + + def __init__(self, property_: OWLObjectPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): + super().__init__(property_=property_, annotations=annotations) + + +class OWLInverseFunctionalObjectPropertyAxiom(OWLObjectPropertyCharacteristicAxiom): + """Represents InverseFunctionalObjectProperty axioms in the OWL 2 specification.""" + __slots__ = () + + def __init__(self, property_: OWLObjectPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): + super().__init__(property_=property_, annotations=annotations) + + +class OWLIrreflexiveObjectPropertyAxiom(OWLObjectPropertyCharacteristicAxiom): + """Represents IrreflexiveObjectProperty axioms in the OWL 2 specification.""" + __slots__ = () + + def __init__(self, property_: OWLObjectPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): + super().__init__(property_=property_, annotations=annotations) + + +class OWLReflexiveObjectPropertyAxiom(OWLObjectPropertyCharacteristicAxiom): + """Represents ReflexiveObjectProperty axioms in the OWL 2 specification.""" + __slots__ = () + + def __init__(self, property_: OWLObjectPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): + super().__init__(property_=property_, annotations=annotations) + + +class OWLSymmetricObjectPropertyAxiom(OWLObjectPropertyCharacteristicAxiom): + """Represents SymmetricObjectProperty axioms in the OWL 2 specification.""" + __slots__ = () + + def __init__(self, property_: OWLObjectPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): + super().__init__(property_=property_, annotations=annotations) + + +class OWLTransitiveObjectPropertyAxiom(OWLObjectPropertyCharacteristicAxiom): + """Represents TransitiveObjectProperty axioms in the OWL 2 specification.""" + __slots__ = () + + def __init__(self, property_: OWLObjectPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): + super().__init__(property_=property_, annotations=annotations) + + +class OWLDataPropertyCharacteristicAxiom(OWLUnaryPropertyAxiom[OWLDataPropertyExpression], + OWLDataPropertyAxiom, metaclass=ABCMeta): + """Base interface for Functional data property axiom.""" + __slots__ = () + + @abstractmethod + def __init__(self, property_: OWLDataPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): + super().__init__(property_=property_, annotations=annotations) + + def __eq__(self, other): + if type(other) is type(self): + return self._property == other._property and self._annotations == other._annotations + return NotImplemented + + def __hash__(self): + return hash((self._property, *self._annotations)) + + def __repr__(self): + return f"{type(self).__name__}({repr(self._property)},{repr(self._annotations)})" + + +class OWLFunctionalDataPropertyAxiom(OWLDataPropertyCharacteristicAxiom): + """Represents FunctionalDataProperty axioms in the OWL 2 specification.""" + __slots__ = () + + def __init__(self, property_: OWLDataPropertyExpression, annotations: Optional[Iterable[OWLAnnotation]] = None): + super().__init__(property_=property_, annotations=annotations) + + +class OWLPropertyDomainAxiom(Generic[_P], OWLUnaryPropertyAxiom[_P], metaclass=ABCMeta): + """Represents ObjectPropertyDomain axioms in the OWL 2 specification.""" + __slots__ = '_domain' + + _domain: OWLClassExpression + + @abstractmethod + def __init__(self, property_: _P, domain: OWLClassExpression, + annotations: Optional[Iterable[OWLAnnotation]] = None): + self._domain = domain + super().__init__(property_=property_, annotations=annotations) + + def get_domain(self) -> OWLClassExpression: + return self._domain + + def __eq__(self, other): + if type(other) is type(self): + return self._property == other._property and self._domain == other._domain \ + and self._annotations == other._annotations + return NotImplemented + + def __hash__(self): + return hash((self._property, self._domain, *self._annotations)) + + def __repr__(self): + return f"{type(self).__name__}({repr(self._property)},{repr(self._domain)},{repr(self._annotations)})" + + +class OWLPropertyRangeAxiom(Generic[_P, _R], OWLUnaryPropertyAxiom[_P], metaclass=ABCMeta): + """Represents ObjectPropertyRange axioms in the OWL 2 specification.""" + __slots__ = '_range' + + _range: _R + + @abstractmethod + def __init__(self, property_: _P, range_: _R, annotations: Optional[Iterable[OWLAnnotation]] = None): + self._range = range_ + super().__init__(property_=property_, annotations=annotations) + + def get_range(self) -> _R: + return self._range + + def __eq__(self, other): + if type(other) is type(self): + return self._property == other._property and self._range == other._range \ + and self._annotations == other._annotations + return NotImplemented + + def __hash__(self): + return hash((self._property, self._range, *self._annotations)) + + def __repr__(self): + return f"{type(self).__name__}({repr(self._property)},{repr(self._range)},{repr(self._annotations)})" + + +class OWLObjectPropertyDomainAxiom(OWLPropertyDomainAxiom[OWLObjectPropertyExpression]): + """ Represents a ObjectPropertyDomain axiom in the OWL 2 Specification.""" + __slots__ = () + + def __init__(self, property_: OWLObjectPropertyExpression, domain: OWLClassExpression, + annotations: Optional[Iterable[OWLAnnotation]] = None): + super().__init__(property_=property_, domain=domain, annotations=annotations) + + +class OWLDataPropertyDomainAxiom(OWLPropertyDomainAxiom[OWLDataPropertyExpression]): + """ Represents a DataPropertyDomain axiom in the OWL 2 Specification.""" + __slots__ = () + + def __init__(self, property_: OWLDataPropertyExpression, domain: OWLClassExpression, + annotations: Optional[Iterable[OWLAnnotation]] = None): + super().__init__(property_=property_, domain=domain, annotations=annotations) + + +class OWLObjectPropertyRangeAxiom(OWLPropertyRangeAxiom[OWLObjectPropertyExpression, OWLClassExpression]): + """ Represents a ObjectPropertyRange axiom in the OWL 2 Specification.""" + __slots__ = () + + def __init__(self, property_: OWLObjectPropertyExpression, range_: OWLClassExpression, + annotations: Optional[Iterable[OWLAnnotation]] = None): + super().__init__(property_=property_, range_=range_, annotations=annotations) + + +class OWLDataPropertyRangeAxiom(OWLPropertyRangeAxiom[OWLDataPropertyExpression, OWLDataRange]): + """ Represents a DataPropertyRange axiom in the OWL 2 Specification.""" + __slots__ = () + + def __init__(self, property_: OWLDataPropertyExpression, range_: OWLDataRange, + annotations: Optional[Iterable[OWLAnnotation]] = None): + super().__init__(property_=property_, range_=range_, annotations=annotations) diff --git a/owlapy/owl_data.py b/owlapy/owl_data.py new file mode 100644 index 00000000..8725c9f4 --- /dev/null +++ b/owlapy/owl_data.py @@ -0,0 +1,227 @@ +from .ranges import OWLDataRange + +from .owl_restriction import OWLHasValueRestriction, OWLDataRestriction, OWLDataCardinalityRestriction, OWLQuantifiedDataRestriction +from .owl_literal import OWLLiteral +from .has import HasOperands +from typing import Final, Sequence, Union, Iterable +from .owl_property import OWLDataPropertyExpression +from .owl_class_expression import OWLClassExpression + +class OWLDataComplementOf(OWLDataRange): + """Represents DataComplementOf in the OWL 2 Specification.""" + type_index: Final = 4002 + + _data_range: OWLDataRange + + def __init__(self, data_range: OWLDataRange): + """ + Args: + data_range: Data range to complement. + """ + self._data_range = data_range + + def get_data_range(self) -> OWLDataRange: + """ + Returns: + The wrapped data range. + """ + return self._data_range + + def __repr__(self): + return f"OWLDataComplementOf({repr(self._data_range)})" + + def __eq__(self, other): + if type(other) is type(self): + return self._data_range == other._data_range + return NotImplemented + + def __hash__(self): + return hash(self._data_range) +class OWLDataHasValue(OWLHasValueRestriction[OWLLiteral], OWLDataRestriction): + """Represents DataHasValue restrictions in the OWL 2 Specification.""" + __slots__ = '_property' + + type_index: Final = 3014 + + _property: OWLDataPropertyExpression + + def __init__(self, property: OWLDataPropertyExpression, value: OWLLiteral): + """Gets an OWLDataHasValue restriction. + + Args: + property: The data property that the restriction acts along. + filler: The literal value. + + Returns: + An OWLDataHasValue restriction along the specified property with the specified literal. + """ + super().__init__(value) + self._property = property + + def __repr__(self): + return f"OWLDataHasValue(property={repr(self._property)},value={repr(self._v)})" + + def __eq__(self, other): + if type(other) is type(self): + return self._v == other._v and self._property == other._property + return NotImplemented + + def __hash__(self): + return hash((self._v, self._property)) + + def as_some_values_from(self) -> OWLClassExpression: + """A convenience method that obtains this restriction as an existential restriction with a nominal filler. + + Returns: + The existential equivalent of this value restriction. simp(HasValue(p a)) = some(p {a}). + """ + return OWLDataSomeValuesFrom(self.get_property(), OWLDataOneOf(self.get_filler())) + + def get_property(self) -> OWLDataPropertyExpression: + # documented in parent + return self._property + +class OWLDataMaxCardinality(OWLDataCardinalityRestriction): + """Represents DataMaxCardinality restrictions in the OWL 2 Specification.""" + __slots__ = '_cardinality', '_filler', '_property' + + type_index: Final = 3017 + + def __init__(self, cardinality: int, property: OWLDataPropertyExpression, filler: OWLDataRange): + """ + Args: + cardinality: Cannot be negative. + property: The property that the restriction acts along. + filler: Data range for restriction. + + Returns: + A DataMaxCardinality on the specified property. + """ + super().__init__(cardinality, property, filler) +class OWLDataMinCardinality(OWLDataCardinalityRestriction): + """Represents DataMinCardinality restrictions in the OWL 2 Specification.""" + __slots__ = '_cardinality', '_filler', '_property' + + type_index: Final = 3015 + + def __init__(self, cardinality: int, property: OWLDataPropertyExpression, filler: OWLDataRange): + """ + Args: + cardinality: Cannot be negative. + property: The property that the restriction acts along. + filler: Data range for restriction. + + Returns: + A DataMinCardinality on the specified property. + """ + super().__init__(cardinality, property, filler) +class OWLDataOneOf(OWLDataRange, HasOperands[OWLLiteral]): + """Represents DataOneOf in the OWL 2 Specification.""" + type_index: Final = 4003 + + _values: Sequence[OWLLiteral] + + def __init__(self, values: Union[OWLLiteral, Iterable[OWLLiteral]]): + if isinstance(values, OWLLiteral): + self._values = values, + else: + for _ in values: + assert isinstance(_, OWLLiteral) + self._values = tuple(values) + + def values(self) -> Iterable[OWLLiteral]: + """Gets the values that are in the oneOf. + + Returns: + The values of this {@code DataOneOf} class expression. + """ + yield from self._values + + def operands(self) -> Iterable[OWLLiteral]: + # documented in parent + yield from self.values() + + def __hash__(self): + return hash(self._values) + + def __eq__(self, other): + if type(other) == type(self): + return self._values == other._values + return NotImplemented + + def __repr__(self): + return f'OWLDataOneOf({self._values})' +class OWLDataSomeValuesFrom(OWLQuantifiedDataRestriction): + """Represents a DataSomeValuesFrom restriction in the OWL 2 Specification.""" + __slots__ = '_property' + + type_index: Final = 3012 + + _property: OWLDataPropertyExpression + + def __init__(self, property: OWLDataPropertyExpression, filler: OWLDataRange): + """Gets an OWLDataSomeValuesFrom restriction. + + Args: + property: The data property that the restriction acts along. + filler: The data range that is the filler. + + Returns: + An OWLDataSomeValuesFrom restriction along the specified property with the specified filler. + """ + super().__init__(filler) + self._property = property + + def __repr__(self): + return f"OWLDataSomeValuesFrom(property={repr(self._property)},filler={repr(self._filler)})" + + def __eq__(self, other): + if type(other) is type(self): + return self._filler == other._filler and self._property == other._property + return NotImplemented + + def __hash__(self): + return hash((self._filler, self._property)) + + def get_property(self) -> OWLDataPropertyExpression: + # documented in parent + return self._property +class OWLNaryDataRange(OWLDataRange, HasOperands[OWLDataRange]): + """OWLNaryDataRange.""" + __slots__ = () + + _operands: Sequence[OWLDataRange] + + def __init__(self, operands: Iterable[OWLDataRange]): + """ + Args: + operands: Data ranges. + """ + self._operands = tuple(operands) + + def operands(self) -> Iterable[OWLDataRange]: + # documented in parent + yield from self._operands + + def __repr__(self): + return f'{type(self).__name__}({repr(self._operands)})' + + def __eq__(self, other): + if type(other) == type(self): + return self._operands == other._operands + return NotImplemented + + def __hash__(self): + return hash(self._operands) +class OWLDataUnionOf(OWLNaryDataRange): + """Represents a DataUnionOf data range in the OWL 2 Specification.""" + __slots__ = '_operands' + type_index: Final = 4005 + + _operands: Sequence[OWLDataRange] +class OWLDataIntersectionOf(OWLNaryDataRange): + """Represents DataIntersectionOf in the OWL 2 Specification.""" + __slots__ = '_operands' + type_index: Final = 4004 + + _operands: Sequence[OWLDataRange] \ No newline at end of file diff --git a/owlapy/owl_individual.py b/owlapy/owl_individual.py new file mode 100644 index 00000000..4d9ade9d --- /dev/null +++ b/owlapy/owl_individual.py @@ -0,0 +1,42 @@ +from abc import ABCMeta +from .owlobject import OWLObject, OWLEntity +from .iri import IRI +from typing import Final, Union +class OWLIndividual(OWLObject, metaclass=ABCMeta): + """Represents a named or anonymous individual.""" + __slots__ = () + pass + +class OWLNamedIndividual(OWLIndividual, OWLEntity): + """Represents a Named Individual in the OWL 2 Specification.""" + __slots__ = '_iri' + type_index: Final = 1005 + + _iri: IRI + + def __init__(self, iri: Union[IRI, str]): + """Gets an instance of OWLNamedIndividual that has the specified IRI. + + Args: + iri: an instance of IRI Class or a string representing the iri + + Returns: + An OWLNamedIndividual that has the specified IRI. + """ + if isinstance(iri, IRI): + self._iri = iri + else: + self._iri = IRI.create(iri) + + def get_iri(self) -> IRI: + # TODO:CD: can be deprecated + # documented in parent + return self._iri + + @property + def iri(self): + return self._iri + + @property + def str(self): + return self._iri.as_str() diff --git a/owlapy/owl_literal.py b/owlapy/owl_literal.py new file mode 100644 index 00000000..c6056b3d --- /dev/null +++ b/owlapy/owl_literal.py @@ -0,0 +1,506 @@ +from abc import ABCMeta, abstractmethod +from functools import total_ordering +from .owl_annotation import OWLAnnotationValue +from typing import Final, Optional, Union, TypeVar, Set +from .types import OWLDatatype +from datetime import datetime, date +from pandas import Timedelta +from .owl_class_expression import OWLClass +from owlapy.vocab import OWLRDFVocabulary, XSDVocabulary +from .owl_property import OWLObjectProperty, OWLDataProperty + +Literals = Union['OWLLiteral', int, float, bool, Timedelta, datetime, date, str] #: +_R = TypeVar('_R', bound='OWLPropertyRange') #: + +class OWLLiteral(OWLAnnotationValue, metaclass=ABCMeta): + """Represents a Literal in the OWL 2 Specification.""" + __slots__ = () + + type_index: Final = 4008 + + def __new__(cls, value, type_: Optional[OWLDatatype] = None): + """Convenience method that obtains a literal. + + Args: + value: The value of the literal. + type_: The datatype of the literal. + """ + if type_ is not None: + if type_ == BooleanOWLDatatype: + return super().__new__(_OWLLiteralImplBoolean) + elif type_ == IntegerOWLDatatype: + return super().__new__(_OWLLiteralImplInteger) + elif type_ == DoubleOWLDatatype: + return super().__new__(_OWLLiteralImplDouble) + elif type_ == StringOWLDatatype: + return super().__new__(_OWLLiteralImplString) + elif type_ == DateOWLDatatype: + return super().__new__(_OWLLiteralImplDate) + elif type_ == DateTimeOWLDatatype: + return super().__new__(_OWLLiteralImplDateTime) + elif type_ == DurationOWLDatatype: + return super().__new__(_OWLLiteralImplDuration) + else: + return super().__new__(_OWLLiteralImpl) + if isinstance(value, bool): + return super().__new__(_OWLLiteralImplBoolean) + elif isinstance(value, int): + return super().__new__(_OWLLiteralImplInteger) + elif isinstance(value, float): + return super().__new__(_OWLLiteralImplDouble) + elif isinstance(value, str): + return super().__new__(_OWLLiteralImplString) + elif isinstance(value, datetime): + return super().__new__(_OWLLiteralImplDateTime) + elif isinstance(value, date): + return super().__new__(_OWLLiteralImplDate) + elif isinstance(value, Timedelta): + return super().__new__(_OWLLiteralImplDuration) + # TODO XXX + raise NotImplementedError(value) + + def get_literal(self) -> str: + """Gets the lexical value of this literal. Note that the language tag is not included. + + Returns: + The lexical value of this literal. + """ + return str(self._v) + + def is_boolean(self) -> bool: + """Whether this literal is typed as boolean.""" + return False + + def parse_boolean(self) -> bool: + """Parses the lexical value of this literal into a bool. The lexical value of this literal should be in the + lexical space of the boolean datatype ("http://www.w3.org/2001/XMLSchema#boolean"). + + Returns: + A bool value that is represented by this literal. + """ + raise ValueError + + def is_double(self) -> bool: + """Whether this literal is typed as double.""" + return False + + def parse_double(self) -> float: + """Parses the lexical value of this literal into a double. The lexical value of this literal should be in the + lexical space of the double datatype ("http://www.w3.org/2001/XMLSchema#double"). + + Returns: + A double value that is represented by this literal. + """ + raise ValueError + + def is_integer(self) -> bool: + """Whether this literal is typed as integer.""" + return False + + def parse_integer(self) -> int: + """Parses the lexical value of this literal into an integer. The lexical value of this literal should be in the + lexical space of the integer datatype ("http://www.w3.org/2001/XMLSchema#integer"). + + Returns: + An integer value that is represented by this literal. + """ + raise ValueError + + def is_string(self) -> bool: + """Whether this literal is typed as string.""" + return False + + def parse_string(self) -> str: + """Parses the lexical value of this literal into a string. The lexical value of this literal should be in the + lexical space of the string datatype ("http://www.w3.org/2001/XMLSchema#string"). + + Returns: + A string value that is represented by this literal. + """ + raise ValueError + + def is_date(self) -> bool: + """Whether this literal is typed as date.""" + return False + + def parse_date(self) -> date: + """Parses the lexical value of this literal into a date. The lexical value of this literal should be in the + lexical space of the date datatype ("http://www.w3.org/2001/XMLSchema#date"). + + Returns: + A date value that is represented by this literal. + """ + raise ValueError + + def is_datetime(self) -> bool: + """Whether this literal is typed as dateTime.""" + return False + + def parse_datetime(self) -> datetime: + """Parses the lexical value of this literal into a datetime. The lexical value of this literal should be in the + lexical space of the dateTime datatype ("http://www.w3.org/2001/XMLSchema#dateTime"). + + Returns: + A datetime value that is represented by this literal. + """ + raise ValueError + + def is_duration(self) -> bool: + """Whether this literal is typed as duration.""" + return False + + def parse_duration(self) -> Timedelta: + """Parses the lexical value of this literal into a Timedelta. The lexical value of this literal should be in the + lexical space of the duration datatype ("http://www.w3.org/2001/XMLSchema#duration"). + + Returns: + A Timedelta value that is represented by this literal. + """ + raise ValueError + + # noinspection PyMethodMayBeStatic + def is_literal(self) -> bool: + # documented in parent + return True + + def as_literal(self) -> 'OWLLiteral': + # documented in parent + return self + + def to_python(self) -> Literals: + return self._v + + @abstractmethod + def get_datatype(self) -> OWLDatatype: + """Gets the OWLDatatype which types this literal. + + Returns: + The OWLDatatype that types this literal. + """ + pass +@total_ordering +class _OWLLiteralImplDouble(OWLLiteral): + __slots__ = '_v' + + _v: float + + def __init__(self, value, type_=None): + assert type_ is None or type_ == DoubleOWLDatatype + if not isinstance(value, float): + value = float(value) + self._v = value + + def __eq__(self, other): + if type(other) is type(self): + return self._v == other._v + return NotImplemented + + def __lt__(self, other): + if type(other) is type(self): + return self._v < other._v + return NotImplemented + + def __hash__(self): + return hash(self._v) + + def __repr__(self): + return f'OWLLiteral({self._v})' + + def is_double(self) -> bool: + return True + + def parse_double(self) -> float: + # documented in parent + return self._v + + # noinspection PyMethodMayBeStatic + def get_datatype(self) -> OWLDatatype: + # documented in parent + return DoubleOWLDatatype +@total_ordering +class _OWLLiteralImplInteger(OWLLiteral): + __slots__ = '_v' + + _v: int + + def __init__(self, value, type_=None): + assert type_ is None or type_ == IntegerOWLDatatype + if not isinstance(value, int): + value = int(value) + self._v = value + + def __eq__(self, other): + if type(other) is type(self): + return self._v == other._v + return NotImplemented + + def __lt__(self, other): + if type(other) is type(self): + return self._v < other._v + return NotImplemented + + def __hash__(self): + return hash(self._v) + + def __repr__(self): + return f'OWLLiteral({self._v})' + + def is_integer(self) -> bool: + return True + + def parse_integer(self) -> int: + # documented in parent + return self._v + + # noinspection PyMethodMayBeStatic + def get_datatype(self) -> OWLDatatype: + # documented in parent + return IntegerOWLDatatype +class _OWLLiteralImplBoolean(OWLLiteral): + __slots__ = '_v' + + _v: bool + + def __init__(self, value, type_=None): + assert type_ is None or type_ == BooleanOWLDatatype + if not isinstance(value, bool): + from distutils.util import strtobool + value = bool(strtobool(value)) + self._v = value + + def __eq__(self, other): + if type(other) is type(self): + return self._v == other._v + return NotImplemented + + def __hash__(self): + return hash(self._v) + + def __repr__(self): + return f'OWLLiteral({self._v})' + + def is_boolean(self) -> bool: + return True + + def parse_boolean(self) -> bool: + # documented in parent + return self._v + + # noinspection PyMethodMayBeStatic + def get_datatype(self) -> OWLDatatype: + # documented in parent + return BooleanOWLDatatype +@total_ordering +class _OWLLiteralImplString(OWLLiteral): + __slots__ = '_v' + + _v: str + + def __init__(self, value, type_=None): + assert type_ is None or type_ == StringOWLDatatype + if not isinstance(value, str): + value = str(value) + self._v = value + + def __eq__(self, other): + if type(other) is type(self): + return self._v == other._v + return NotImplemented + + def __lt__(self, other): + if type(other) is type(self): + return self._v < other._v + return NotImplemented + + def __len__(self): + return len(self._v) + + def __hash__(self): + return hash(self._v) + + def __repr__(self): + return f'OWLLiteral({self._v})' + + def is_string(self) -> bool: + return True + + def parse_string(self) -> str: + # documented in parent + return self._v + + # noinspection PyMethodMayBeStatic + def get_datatype(self) -> OWLDatatype: + # documented in parent + return StringOWLDatatype +@total_ordering +class _OWLLiteralImplDate(OWLLiteral): + __slots__ = '_v' + + _v: date + + def __init__(self, value, type_=None): + assert type_ is None or type_ == DateOWLDatatype + if not isinstance(value, date): + value = date.fromisoformat(value) + self._v = value + + def __eq__(self, other): + if type(other) is type(self): + return self._v == other._v + return NotImplemented + + def __lt__(self, other): + if type(other) is type(self): + return self._v < other._v + return NotImplemented + + def __hash__(self): + return hash(self._v) + + def __repr__(self): + return f'OWLLiteral({self._v})' + + def is_date(self) -> bool: + return True + + def parse_date(self) -> date: + # documented in parent + return self._v + + # noinspection PyMethodMayBeStatic + def get_datatype(self) -> OWLDatatype: + # documented in parent + return DateOWLDatatype + + +@total_ordering +class _OWLLiteralImplDateTime(OWLLiteral): + __slots__ = '_v' + + _v: datetime + + def __init__(self, value, type_=None): + assert type_ is None or type_ == DateTimeOWLDatatype + if not isinstance(value, datetime): + value = value.replace("Z", "+00:00") if isinstance(value, str) and value[-1] == "Z" else value + value = datetime.fromisoformat(value) + self._v = value + + def __eq__(self, other): + if type(other) is type(self): + return self._v == other._v + return NotImplemented + + def __lt__(self, other): + if type(other) is type(self): + return self._v < other._v + return NotImplemented + + def __hash__(self): + return hash(self._v) + + def __repr__(self): + return f'OWLLiteral({self._v})' + + def is_datetime(self) -> bool: + return True + + def parse_datetime(self) -> datetime: + # documented in parent + return self._v + + # noinspection PyMethodMayBeStatic + def get_datatype(self) -> OWLDatatype: + # documented in parent + return DateTimeOWLDatatype + + +@total_ordering +class _OWLLiteralImplDuration(OWLLiteral): + __slots__ = '_v' + + _v: Timedelta + + def __init__(self, value, type_=None): + assert type_ is None or type_ == DurationOWLDatatype + if not isinstance(value, Timedelta): + value = Timedelta(value) + self._v = value + + def get_literal(self) -> str: + return self._v.isoformat() + + def __eq__(self, other): + if type(other) is type(self): + return self._v == other._v + return NotImplemented + + def __lt__(self, other): + if type(other) is type(self): + return self._v < other._v + return NotImplemented + + def __hash__(self): + return hash(self._v) + + def __repr__(self): + return f'OWLLiteral({self._v})' + + def is_duration(self) -> bool: + return True + + def parse_duration(self) -> Timedelta: + # documented in parent + return self._v + + # noinspection PyMethodMayBeStatic + def get_datatype(self) -> OWLDatatype: + # documented in parent + return DurationOWLDatatype + + +class _OWLLiteralImpl(OWLLiteral): + __slots__ = '_v', '_datatype' + + def __init__(self, v, type_: OWLDatatype): + assert isinstance(type_, OWLDatatype) + self._v = v + self._datatype = type_ + + def get_datatype(self) -> OWLDatatype: + return self._datatype + + def __eq__(self, other): + if type(other) is type(self) and other.get_datatype() == self.get_datatype(): + return self._v == other._v + return NotImplemented + + def __hash__(self): + return hash((self._v, self._datatype)) + + def __repr__(self): + return f'OWLLiteral({repr(self._v)}, {self._datatype})' + +OWLThing: Final = OWLClass(OWLRDFVocabulary.OWL_THING.get_iri()) #: : :The OWL Class corresponding to owl:Thing +OWLNothing: Final = OWLClass(OWLRDFVocabulary.OWL_NOTHING.get_iri()) #: : :The OWL Class corresponding to owl:Nothing +#: the built in top object property +OWLTopObjectProperty: Final = OWLObjectProperty(OWLRDFVocabulary.OWL_TOP_OBJECT_PROPERTY.get_iri()) +#: the built in bottom object property +OWLBottomObjectProperty: Final = OWLObjectProperty(OWLRDFVocabulary.OWL_BOTTOM_OBJECT_PROPERTY.get_iri()) +#: the built in top data property +OWLTopDataProperty: Final = OWLDataProperty(OWLRDFVocabulary.OWL_TOP_DATA_PROPERTY.get_iri()) +#: the built in bottom data property +OWLBottomDataProperty: Final = OWLDataProperty(OWLRDFVocabulary.OWL_BOTTOM_DATA_PROPERTY.get_iri()) + +DoubleOWLDatatype: Final = OWLDatatype(XSDVocabulary.DOUBLE) #: An object representing a double datatype. +IntegerOWLDatatype: Final = OWLDatatype(XSDVocabulary.INTEGER) #: An object representing an integer datatype. +BooleanOWLDatatype: Final = OWLDatatype(XSDVocabulary.BOOLEAN) #: An object representing the boolean datatype. +StringOWLDatatype: Final = OWLDatatype(XSDVocabulary.STRING) #: An object representing the string datatype. +DateOWLDatatype: Final = OWLDatatype(XSDVocabulary.DATE) #: An object representing the date datatype. +DateTimeOWLDatatype: Final = OWLDatatype(XSDVocabulary.DATE_TIME) #: An object representing the dateTime datatype. +DurationOWLDatatype: Final = OWLDatatype(XSDVocabulary.DURATION) #: An object representing the duration datatype. +#: The OWL Datatype corresponding to the top data type +TopOWLDatatype: Final = OWLDatatype(OWLRDFVocabulary.RDFS_LITERAL) + +NUMERIC_DATATYPES: Final[Set[OWLDatatype]] = {DoubleOWLDatatype, IntegerOWLDatatype} +TIME_DATATYPES: Final[Set[OWLDatatype]] = {DateOWLDatatype, DateTimeOWLDatatype, DurationOWLDatatype} diff --git a/owlapy/owl_property.py b/owlapy/owl_property.py index 599d7b61..5a89984a 100644 --- a/owlapy/owl_property.py +++ b/owlapy/owl_property.py @@ -68,6 +68,7 @@ class OWLDataPropertyExpression(OWLPropertyExpression, metaclass=ABCMeta): def is_data_property_expression(self): # documented in parent return True + class OWLProperty(OWLPropertyExpression, OWLEntity, metaclass=ABCMeta): """A marker interface for properties that aren't expression i.e. named properties. By definition, properties are either data properties or object properties.""" diff --git a/owlapy/owl_restriction.py b/owlapy/owl_restriction.py index a544674e..2515e981 100644 --- a/owlapy/owl_restriction.py +++ b/owlapy/owl_restriction.py @@ -2,8 +2,8 @@ from .has import HasFiller, HasCardinality from typing import TypeVar, Generic, Final from .owl_class_expression import OWLAnonymousClassExpression, OWLClassExpression, OWLObjectIntersectionOf -from .owl_property import OWLPropertyExpression, OWLObjectPropertyExpression -from .ranges import OWLPropertyRange +from .owl_property import OWLPropertyExpression, OWLObjectPropertyExpression, OWLDataPropertyExpression +from .ranges import OWLPropertyRange, OWLDataRange _T = TypeVar('_T') #: _F = TypeVar('_F', bound=OWLPropertyRange) #: @@ -298,3 +298,110 @@ def __hash__(self): def __repr__(self): return f'OWLObjectHasSelf({self._property})' + + +class OWLQuantifiedDataRestriction(OWLQuantifiedRestriction[OWLDataRange], + OWLDataRestriction, metaclass=ABCMeta): + """Represents a quantified data restriction.""" + __slots__ = () + + _filler: OWLDataRange + + def __init__(self, filler: OWLDataRange): + self._filler = filler + + def get_filler(self) -> OWLDataRange: + # documented in parent (HasFiller) + return self._filler +class OWLDataAllValuesFrom(OWLQuantifiedDataRestriction): + """Represents DataAllValuesFrom class expressions in the OWL 2 Specification.""" + __slots__ = '_property' + + type_index: Final = 3013 + + _property: OWLDataPropertyExpression + + def __init__(self, property: OWLDataPropertyExpression, filler: OWLDataRange): + """Gets an OWLDataAllValuesFrom restriction. + + Args: + property: The data property that the restriction acts along. + filler: The data range that is the filler. + + Returns: + An OWLDataAllValuesFrom restriction along the specified property with the specified filler. + """ + super().__init__(filler) + self._property = property + + def __repr__(self): + return f"OWLDataAllValuesFrom(property={repr(self._property)},filler={repr(self._filler)})" + + def __eq__(self, other): + if type(other) is type(self): + return self._filler == other._filler and self._property == other._property + return NotImplemented + + def __hash__(self): + return hash((self._filler, self._property)) + + def get_property(self) -> OWLDataPropertyExpression: + # documented in parent + return self._property +class OWLDataCardinalityRestriction(OWLCardinalityRestriction[OWLDataRange], + OWLQuantifiedDataRestriction, + OWLDataRestriction, metaclass=ABCMeta): + """Represents Data Property Cardinality Restrictions in the OWL 2 specification.""" + __slots__ = () + + _property: OWLDataPropertyExpression + + @abstractmethod + def __init__(self, cardinality: int, property: OWLDataPropertyExpression, filler: OWLDataRange): + super().__init__(cardinality, filler) + self._property = property + + def get_property(self) -> OWLDataPropertyExpression: + # documented in parent + return self._property + + def __repr__(self): + return f"{type(self).__name__}(" \ + f"property={repr(self.get_property())},{self.get_cardinality()},filler={repr(self.get_filler())})" + + def __eq__(self, other): + if type(other) == type(self): + return self._property == other._property \ + and self._cardinality == other._cardinality \ + and self._filler == other._filler + return NotImplemented + + def __hash__(self): + return hash((self._property, self._cardinality, self._filler)) + +class OWLDataExactCardinality(OWLDataCardinalityRestriction): + """Represents DataExactCardinality restrictions in the OWL 2 Specification.""" + __slots__ = '_cardinality', '_filler', '_property' + + type_index: Final = 3016 + + def __init__(self, cardinality: int, property: OWLDataPropertyExpression, filler: OWLDataRange): + """ + Args: + cardinality: Cannot be negative. + property: The property that the restriction acts along. + filler: Data range for restriction + + Returns: + A DataExactCardinality on the specified property. + """ + super().__init__(cardinality, property, filler) + + def as_intersection_of_min_max(self) -> OWLObjectIntersectionOf: + """Obtains an equivalent form that is a conjunction of a min cardinality and max cardinality restriction. + + Returns: + The semantically equivalent but structurally simpler form (= 1 R D) = >= 1 R D and <= 1 R D. + """ + args = self.get_cardinality(), self.get_property(), self.get_filler() + return OWLObjectIntersectionOf((OWLDataMinCardinality(*args), OWLDataMaxCardinality(*args))) diff --git a/owlapy/types.py b/owlapy/types.py new file mode 100644 index 00000000..9c5eaeaf --- /dev/null +++ b/owlapy/types.py @@ -0,0 +1,29 @@ +from .owlobject import OWLObject, OWLEntity +from .ranges import OWLDataRange +from .iri import IRI +from .has import HasIRI +from typing import Final, Union + +class OWLDatatype(OWLEntity, OWLDataRange): + """Represents a Datatype (named data range) in the OWL 2 Specification.""" + __slots__ = '_iri' + + type_index: Final = 4001 + + _iri: IRI + + def __init__(self, iri: Union[IRI, HasIRI]): + """Gets an instance of OWLDatatype that has the specified IRI. + + Args: + iri: The IRI. + """ + if isinstance(iri, HasIRI): + self._iri = iri.get_iri() + else: + assert isinstance(iri, IRI) + self._iri = iri + + def get_iri(self) -> IRI: + # documented in parent + return self._iri