Skip to content

Commit

Permalink
Merge pull request #21 from dice-group/refactoring_owl
Browse files Browse the repository at this point in the history
Refactoring OWLAPY/model
  • Loading branch information
Demirrr authored Apr 9, 2024
2 parents 3d3aad5 + 0e52d17 commit c4a34eb
Show file tree
Hide file tree
Showing 19 changed files with 533 additions and 508 deletions.
72 changes: 1 addition & 71 deletions owlapy/has.py
Original file line number Diff line number Diff line change
@@ -1,77 +1,7 @@
from typing import Protocol, ClassVar, TypeVar, Generic, Iterable
from abc import ABCMeta, abstractmethod
_T = TypeVar('_T') #:

from typing import Protocol, ClassVar
class HasIndex(Protocol):
"""Interface for types with an index; this is used to group objects by type when sorting."""
type_index: ClassVar[int] #: index for this type. This is a sorting index for the types.

def __eq__(self, other): ...


class HasIRI(metaclass=ABCMeta):
"""Simple class to access the IRI."""
__slots__ = ()

@abstractmethod
def get_iri(self) -> 'IRI':
"""Gets the IRI of this object.
Returns:
The IRI of this object.
"""
pass


class HasOperands(Generic[_T], metaclass=ABCMeta):
"""An interface to objects that have a collection of operands.
Args:
_T: Operand type.
"""
__slots__ = ()

@abstractmethod
def operands(self) -> Iterable[_T]:
"""Gets the operands - e.g., the individuals in a sameAs axiom, or the classes in an equivalent
classes axiom.
Returns:
The operands.
"""
pass



class HasFiller(Generic[_T], metaclass=ABCMeta):
"""An interface to objects that have a filler.
Args:
_T: Filler type.
"""
__slots__ = ()

@abstractmethod
def get_filler(self) -> _T:
"""Gets the filler for this restriction. In the case of an object restriction this will be an individual, in
the case of a data restriction this will be a constant (data value). For quantified restriction this will be
a class expression or a data range.
Returns:
the value
"""
pass


class HasCardinality(metaclass=ABCMeta):
"""An interface to objects that have a cardinality."""
__slots__ = ()

@abstractmethod
def get_cardinality(self) -> int:
"""Gets the cardinality of a restriction.
Returns:
The cardinality. A non-negative integer.
"""
pass
72 changes: 72 additions & 0 deletions owlapy/meta_classes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# https://docs.python.org/3/reference/datamodel.html#metaclasses
from typing import TypeVar, Generic, Iterable
from abc import ABCMeta, abstractmethod

_T = TypeVar('_T') #:


class HasIRI(metaclass=ABCMeta):
"""Simple class to access the IRI."""
__slots__ = ()

@abstractmethod
def get_iri(self) -> 'IRI':
"""Gets the IRI of this object.
Returns:
The IRI of this object.
"""
pass


class HasOperands(Generic[_T], metaclass=ABCMeta):
"""An interface to objects that have a collection of operands.
Args:
_T: Operand type.
"""
__slots__ = ()

@abstractmethod
def operands(self) -> Iterable[_T]:
"""Gets the operands - e.g., the individuals in a sameAs axiom, or the classes in an equivalent
classes axiom.
Returns:
The operands.
"""
pass


class HasFiller(Generic[_T], metaclass=ABCMeta):
"""An interface to objects that have a filler.
Args:
_T: Filler type.
"""
__slots__ = ()

@abstractmethod
def get_filler(self) -> _T:
"""Gets the filler for this restriction. In the case of an object restriction this will be an individual, in
the case of a data restriction this will be a constant (data value). For quantified restriction this will be
a class expression or a data range.
Returns:
the value
"""
pass


class HasCardinality(metaclass=ABCMeta):
"""An interface to objects that have a cardinality."""
__slots__ = ()

@abstractmethod
def get_cardinality(self) -> int:
"""Gets the cardinality of a restriction.
Returns:
The cardinality. A non-negative integer.
"""
pass
166 changes: 6 additions & 160 deletions owlapy/model/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
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
Expand All @@ -8,25 +7,25 @@
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.has import HasIndex
from owlapy.meta_classes import HasIRI, HasOperands, HasFiller, HasCardinality
from owlapy.owl_class_expression import OWLNaryBooleanClassExpression, OWLClassExpression, OWLObjectComplementOf, \
OWLAnonymousClassExpression, OWLBooleanClassExpression, OWLPropertyRange, OWLDataRange, OWLClass, OWLObjectUnionOf, \
OWLObjectIntersectionOf
OWLObjectIntersectionOf, OWLThing, OWLNothing
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)
OWLObjectHasSelf, OWLObjectMaxCardinality, OWLObjectExactCardinality,OWLDataExactCardinality,OWLDataMinCardinality,
OWLDataMaxCardinality,OWLDataSomeValuesFrom,OWLDataHasValue,OWLDataOneOf,OWLQuantifiedDataRestriction,OWLDataCardinalityRestriction)

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


Expand All @@ -40,89 +39,6 @@
_M = TypeVar('_M', bound='OWLOntologyManager') #:


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 OWLOntologyID:
Expand Down Expand Up @@ -188,75 +104,6 @@ def __eq__(self, other):
return NotImplemented


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 OWLImportsDeclaration(HasIRI):
"""Represents an import statement in an ontology."""
Expand Down Expand Up @@ -925,8 +772,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
OWLTopObjectProperty: Final = OWLObjectProperty(OWLRDFVocabulary.OWL_TOP_OBJECT_PROPERTY.get_iri())
#: the built in bottom object property
Expand Down
3 changes: 2 additions & 1 deletion owlapy/model/providers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""OWL Datatype restriction constructors."""
from typing import Union
from datetime import datetime, date
from owlapy.model import OWLDatatypeRestriction, OWLFacet, OWLFacetRestriction, OWLLiteral
from owlapy.owl_literal import OWLLiteral
from owlapy.owl_restriction import OWLDatatypeRestriction, OWLFacet, OWLFacetRestriction
from pandas import Timedelta

Restriction_Literals = Union[OWLLiteral, int, float, Timedelta, datetime, date]
Expand Down
2 changes: 1 addition & 1 deletion owlapy/owl_axiom.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from .owl_property import OWLDataPropertyExpression, OWLObjectPropertyExpression
from .owlobject import OWLObject, OWLEntity
from .types import OWLDatatype, OWLDataRange
from .has import HasOperands
from .meta_classes import HasOperands
from .owl_property import OWLPropertyExpression, OWLProperty
from .owl_class_expression import OWLClassExpression, OWLClass
from .owl_individual import OWLIndividual
Expand Down
Loading

0 comments on commit c4a34eb

Please sign in to comment.