Skip to content

Commit

Permalink
Merge pull request #17 from dice-group/refactoring_sparql_mapping
Browse files Browse the repository at this point in the history
Refactoring sparql mapping
  • Loading branch information
Demirrr authored Apr 8, 2024
2 parents 34ab379 + ca50e59 commit 2fa7b73
Show file tree
Hide file tree
Showing 11 changed files with 123 additions and 123 deletions.
42 changes: 42 additions & 0 deletions owlapy/has.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from typing import Protocol, ClassVar, TypeVar, Generic, Iterable
from abc import ABCMeta, abstractmethod
_T = TypeVar('_T') #:

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
43 changes: 0 additions & 43 deletions owlapy/io.py

This file was deleted.

16 changes: 1 addition & 15 deletions owlapy/model/_iri.py → owlapy/iri.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,10 @@
from weakref import WeakKeyDictionary

from owlapy import namespaces
from owlapy.model._base import OWLAnnotationSubject, OWLAnnotationValue
from owlapy.owlobject import OWLAnnotationSubject, OWLAnnotationValue
from owlapy.namespaces import Namespaces


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 _WeakCached(type):
__slots__ = ()

Expand Down
31 changes: 3 additions & 28 deletions owlapy/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@

from owlapy.vocab import OWLRDFVocabulary, XSDVocabulary, OWLFacet
from owlapy._utils import MOVE
from owlapy.model._base import OWLObject, OWLAnnotationObject, OWLAnnotationSubject, OWLAnnotationValue
from owlapy.model._iri import HasIRI, IRI
from owlapy.owlobject import OWLObject, OWLAnnotationObject, OWLAnnotationSubject, OWLAnnotationValue
from owlapy.iri import IRI
from owlapy.has import HasIndex, HasIRI, HasOperands

MOVE(OWLObject, OWLAnnotationObject, OWLAnnotationSubject, OWLAnnotationValue, HasIRI, IRI)

Expand All @@ -21,32 +22,6 @@
Literals = Union['OWLLiteral', int, float, bool, Timedelta, datetime, date, str] #:


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 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 OWLPropertyRange(OWLObject, metaclass=ABCMeta):
"""OWL Objects that can be the ranges of properties."""

Expand Down
43 changes: 22 additions & 21 deletions owlapy/owl2sparql/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class Owl2SparqlConverter:
"""Convert owl (owlapy model class expressions) to SPARQL."""
__slots__ = 'ce', 'sparql', 'variables', 'parent', 'parent_var', 'properties', 'variable_entities', 'cnt', \
'mapping', 'grouping_vars', 'having_conditions', '_intersection'
# @TODO:CD: We need to document this class. The computation behind the mapping is not clear.

ce: OWLClassExpression
sparql: List[str]
Expand Down Expand Up @@ -130,10 +131,6 @@ def convert(self, root_variable: str, ce: OWLClassExpression, named_individuals:
def modal_depth(self):
return len(self.variables)

# @property
# def in_intersection(self):
# return self._intersection[self.modal_depth]

@singledispatchmethod
def render(self, e):
raise NotImplementedError(e)
Expand Down Expand Up @@ -174,13 +171,6 @@ def _maybe_render(self, o):
else:
return self.render(o)

# @contextmanager
# def intersection(self):
# self._intersection[self.modal_depth] = True
# try:
# yield
# finally:
# del self._intersection[self.modal_depth]

@contextmanager
def stack_variable(self, var):
Expand Down Expand Up @@ -559,13 +549,17 @@ def as_query(self,
ce: OWLClassExpression,
count: bool = False,
values: Optional[Iterable[OWLNamedIndividual]] = None,
named_individuals: bool = False):
# root variable: the variable that will be projected
# ce: the class expression to be transformed to a SPARQL query
# count: True, counts the results ; False, projects the individuals
# values: positive or negative examples from a class expression problem
# named_individuals: if set to True, the generated SPARQL query will return only entities that are instances
# of owl:NamedIndividual
named_individuals: bool = False)->str:
"""
root variable: the variable that will be projected
ce: the class expression to be transformed to a SPARQL query
count: True, counts the results ; False, projects the individuals
values: positive or negative examples from a class expression problem
named_individuals: if set to True, the generated SPARQL query will return only entities that are instances
of owl:NamedIndividual
"""

qs = ["SELECT"]
tp = self.convert(root_variable, ce, named_individuals)
if count:
Expand All @@ -592,8 +586,15 @@ def as_query(self,

def owl_expression_to_sparql(root_variable: str = "?x",
expression: OWLClassExpression = None,
count: bool = False,
values: Optional[Iterable[OWLNamedIndividual]] = None,
named_individuals: bool = False)->str:
"""Convert an OWL Class Expression (https://www.w3.org/TR/owl2-syntax/#Class_Expressions) into a SPARQL query"""
return converter.as_query(root_variable, expression, count, values, named_individuals)
"""Convert an OWL Class Expression (https://www.w3.org/TR/owl2-syntax/#Class_Expressions) into a SPARQL query
root variable: the variable that will be projected
expression: the class expression to be transformed to a SPARQL query
values: positive or negative examples from a class expression problem. Unclear
named_individuals: if set to True, the generated SPARQL query will return only entities
that are instances of owl:NamedIndividual
"""
assert expression is not None, "expression cannot be None"
return converter.as_query(root_variable, expression, False, values, named_individuals)
49 changes: 41 additions & 8 deletions owlapy/model/_base.py → owlapy/owlobject.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
from abc import ABCMeta, abstractmethod
from typing import Optional, TYPE_CHECKING

if TYPE_CHECKING:
from owlapy.model._iri import IRI
from owlapy.model import OWLLiteral


from abc import abstractmethod, ABCMeta
from typing import Optional
class OWLObject(metaclass=ABCMeta):
"""Base interface for OWL objects"""
__slots__ = ()
Expand All @@ -27,6 +21,45 @@ def is_anonymous(self) -> bool:
return True



class OWLObjectRenderer(metaclass=ABCMeta):
"""Abstract class with a render method to render an OWL Object into a string."""
@abstractmethod
def set_short_form_provider(self, short_form_provider) -> None:
"""Configure a short form provider that shortens the OWL objects during rendering.
Args:
short_form_provider: Short form provider.
"""
pass

@abstractmethod
def render(self, o: OWLObject) -> str:
"""Render OWL Object to string.
Args:
o: OWL Object.
Returns:
String rendition of OWL object.
"""
pass


class OWLObjectParser(metaclass=ABCMeta):
"""Abstract class with a parse method to parse a string to an OWL Object."""
@abstractmethod
def parse_expression(self, expression_str: str) -> OWLObject:
"""Parse a string to an OWL Object.
Args:
expression_str (str): Expression string.
Returns:
The OWL Object which is represented by the string.
"""
pass

class OWLAnnotationObject(OWLObject, metaclass=ABCMeta):
"""A marker interface for the values (objects) of annotations."""
__slots__ = ()
Expand Down
11 changes: 7 additions & 4 deletions owlapy/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
from parsimonious.grammar import Grammar
from parsimonious.nodes import NodeVisitor
from parsimonious.nodes import Node
from owlapy.io import OWLObjectParser
from .owlobject import OWLObjectParser
from .namespaces import Namespaces
from .render import _DL_SYNTAX, _MAN_SYNTAX
from .vocab import OWLFacet, OWLRDFVocabulary


from owlapy.model import OWLObjectHasSelf, OWLObjectIntersectionOf, OWLObjectMinCardinality, OWLObjectOneOf, \
OWLObjectProperty, OWLObjectPropertyExpression, OWLObjectSomeValuesFrom, OWLObjectUnionOf, OWLClass, IRI, \
OWLClassExpression, OWLDataProperty, OWLNamedIndividual, OWLObjectComplementOf, OWLObjectExactCardinality, \
Expand All @@ -14,10 +19,8 @@
OWLDataMaxCardinality, OWLObjectMaxCardinality, OWLDataIntersectionOf, OWLDataMinCardinality, OWLDataHasValue, \
OWLLiteral, OWLDataRange, OWLDataUnionOf, OWLDataOneOf, OWLDatatype, OWLObjectCardinalityRestriction, \
OWLDataCardinalityRestriction, OWLObjectAllValuesFrom, OWLDataAllValuesFrom, OWLDataComplementOf, BooleanOWLDatatype
from owlapy.namespaces import Namespaces

from owlapy.render import _DL_SYNTAX, _MAN_SYNTAX
from owlapy.vocab import OWLFacet, OWLRDFVocabulary



MANCHESTER_GRAMMAR = Grammar(r"""
Expand Down
3 changes: 2 additions & 1 deletion owlapy/render.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
from typing import List, Callable

from owlapy import namespaces
from owlapy.io import OWLObjectRenderer
from .owlobject import OWLObjectRenderer
# from owlapy.io import OWLObjectRenderer
from owlapy.model import OWLLiteral, OWLNaryDataRange, OWLObject, OWLClass, OWLObjectSomeValuesFrom, \
OWLObjectAllValuesFrom, OWLObjectUnionOf, OWLBooleanClassExpression, OWLNaryBooleanClassExpression, \
OWLObjectIntersectionOf, OWLObjectComplementOf, OWLObjectInverseOf, OWLClassExpression, OWLRestriction, \
Expand Down
3 changes: 2 additions & 1 deletion owlapy/util.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""Owlapy utils."""
from functools import singledispatchmethod, total_ordering
from typing import Iterable, List, Type, TypeVar, Generic, Tuple, cast, Optional, Union, overload
from .has import HasIndex

from owlapy.model import HasIndex, HasIRI, OWLClassExpression, OWLClass, OWLObjectCardinalityRestriction, \
from owlapy.model import HasIRI, OWLClassExpression, OWLClass, OWLObjectCardinalityRestriction, \
OWLObjectComplementOf, OWLNothing, OWLPropertyRange, OWLRestriction, OWLThing, OWLObjectSomeValuesFrom, \
OWLObjectHasValue, OWLObjectMinCardinality, OWLObjectMaxCardinality, OWLObjectExactCardinality, OWLObjectHasSelf, \
OWLObjectOneOf, OWLDataMaxCardinality, OWLDataMinCardinality, OWLDataExactCardinality, OWLDataHasValue, \
Expand Down
3 changes: 2 additions & 1 deletion owlapy/vocab.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
from re import match

from owlapy import namespaces
from owlapy.model._iri import HasIRI, IRI
from .has import HasIRI
from .iri import IRI
from owlapy.namespaces import Namespaces


Expand Down
2 changes: 1 addition & 1 deletion tests/test_owlapy_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def test_ce_render(self):
oneof = OWLObjectOneOf((i1, i2))
r = renderer.render(oneof)
print(r)
self.assertEqual(r, "{heinz marie}")
self.assertEqual(r, "{heinz , marie}")

hasvalue = OWLObjectHasValue(property=has_child, individual=i1)
r = renderer.render(hasvalue)
Expand Down

0 comments on commit 2fa7b73

Please sign in to comment.