Skip to content
This repository has been archived by the owner on Jan 4, 2020. It is now read-only.

Commit

Permalink
An OMProperty object is now reversed or not. Uses hydra:reversed entr…
Browse files Browse the repository at this point in the history
…ies. Improves #2.
  • Loading branch information
bcogrel committed Jul 20, 2014
1 parent 9e1661b commit f2a76b6
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 30 deletions.
3 changes: 0 additions & 3 deletions oldman/parsing/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +0,0 @@



1 change: 0 additions & 1 deletion oldman/parsing/schema/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@

20 changes: 14 additions & 6 deletions oldman/parsing/schema/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@ class JsonLdContextAttributeMdExtractor(OMAttributeMdExtractor):
that extract attribute names and datatypes from the JSON-LD context.
"""

def __init__(self):
self._logger = logging.getLogger(__name__)

def update(self, om_properties, context_js, schema_graph):
"""See :func:`oldman.parsing.schema.context.OMAttributeMdExtractor.update`."""
context = Context(context_js)

for property_iri, om_property in om_properties.iteritems():
for (property_iri, reversed), om_property in om_properties.iteritems():
# Efficient search
term = context.find_term(property_iri)
if term:
Expand All @@ -45,15 +48,20 @@ def update(self, om_properties, context_js, schema_graph):
# Not declared (worst case)
elif len(property_iri) == 0:
name = schema_graph.qname(property_iri).replace(":", "_")
logger = logging.getLogger(__name__)
logger.warn(u"No short name found for property %s. QName %s used instead" % (property_iri, name))
self._logger.warn(u"No short name found for property %s. QName %s used instead"
% (property_iri, name))
om_property.add_attribute_metadata(name)

def _update_property(self, om_property, term):
reversed = bool(term.reverse)
if reversed is not om_property.reversed:
self._logger.info(u"The term %s (reversed: %s) does not match with property %s (reversed: %s)"
% (term.name, reversed, om_property.iri, om_property.reversed))
return

kwargs = {'jsonld_type': term.type,
'language': term.language,
'container': term.container,
'reverse': term.reverse}
'container': term.container}
clean_fct = lambda v: None if v == UNDEF else v
kwargs = {k: clean_fct(v) for k, v in kwargs.iteritems()}
om_property.add_attribute_metadata(term.name, **kwargs)
om_property.add_attribute_metadata(term.name, reversed=reversed, **kwargs)
24 changes: 14 additions & 10 deletions oldman/parsing/schema/property.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def update(self, om_properties, class_iri, type_iris, schema_graph, manager):
from the schema graph.
:param om_properties: `dict` of :class:`~oldman.property.OMProperty` objects indexed
by their IRIs.
by their IRIs and their reverse status.
:param class_iri: IRI of RDFS class of the future :class:`~oldman.model.Model` object.
:param type_iris: Ancestry of the RDFS class.
:param schema_graph: :class:`rdflib.graph.Graph` object.
Expand All @@ -34,7 +34,7 @@ class HydraPropertyExtractor(OMPropertyExtractor):
"""

_extract_hydra_properties = u"""
SELECT ?p ?required ?readonly ?writeonly
SELECT ?p ?required ?readonly ?writeonly ?reversed
WHERE {
?class_iri hydra:supportedProperty ?sp.
?sp hydra:property ?p.
Expand All @@ -46,7 +46,10 @@ class HydraPropertyExtractor(OMPropertyExtractor):
} .
OPTIONAL {
?sp hydra:writeonly ?writeonly
}
} .
OPTIONAL {
?sp hydra:reversed ?reversed
} .
}
"""
_ns = {u'hydra': Namespace(u"http://www.w3.org/ns/hydra/core#")}
Expand All @@ -58,20 +61,21 @@ def update(self, om_properties, class_iri, type_iris, schema_graph, manager):
for type_uri in type_iris:
results = schema_graph.query(self._extract_hydra_properties, initNs=self._ns,
initBindings={u'class_iri': URIRef(type_uri)})
for property_iri, is_req, ro, wo in results:
for property_iri, is_req, ro, wo, rev in results:
reversed = bool(rev)
prop_uri = property_iri.toPython()
# Booleans are false by default
is_required, read_only, write_only = prop_params.get(prop_uri, (False, False, False))
is_required, read_only, write_only = prop_params.get((prop_uri, reversed), (False, False, False))

# Updates these booleans
is_required = is_required or (is_req is not None and bool(is_req.toPython()))
read_only = read_only or (ro is not None and bool(ro.toPython()))
write_only = write_only or (wo is not None and bool(wo.toPython()))
prop_params[prop_uri] = (is_required, read_only, write_only)
prop_params[(prop_uri, reversed)] = (is_required, read_only, write_only)

for property_iri, (is_required, read_only, write_only) in prop_params.iteritems():
if not property_iri in om_properties:
for (property_iri, reversed), (is_required, read_only, write_only) in prop_params.iteritems():
if not (property_iri, reversed) in om_properties:
om_property = OMProperty(manager, property_iri, class_iri, is_required=is_required,
read_only=read_only, write_only=write_only)
om_properties[property_iri] = om_property
read_only=read_only, write_only=write_only, reversed=reversed)
om_properties[(property_iri, reversed)] = om_property
return om_properties
33 changes: 24 additions & 9 deletions oldman/property.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,21 @@


class OMProperty(object):
"""An :class:`~oldman.property.OMProperty` object represents a RDF property supported by a RDFS class.
"""An :class:`~oldman.property.OMProperty` object represents the support of a RDF property by a RDFS class.
It gathers some :class:`~oldman.attribute.OMAttribute` objects (usually one).
An :class:`~oldman.property.OMProperty` object is in charge of generating its
:class:`~oldman.attribute.OMAttribute` objects according to the metadata that
has been extracted from the schema and JSON-LD context.
A property can be reversed: the :class:`~oldman.resource.Resource` object
to which the :class:`~oldman.attribute.OMAttribute` objects will be (indirectly)
attached is then the object of this property, not its subject (?o ?p ?s).
Consequently, two :class:`~oldman.property.OMProperty` objects can refer
to the same RDF property when one is reversed while the second is not.
:param manager: :class:`~oldman.management.manager.ResourceManager` object.
:param property_iri: IRI of the RDF property.
:param supporter_class_iri: IRI of the RDFS class that supports the property.
Expand All @@ -23,14 +30,15 @@ class OMProperty(object):
Defaults to `False`.
:param write_only: If `True`, the value of the property cannot be read by a regular end-user.
Defaults to `False`.
:param reversed: If `True`, the property is reversed. Defaults to `False`.
:param cardinality: Defaults to `None`. Not yet supported.
:param property_type: String. In OWL, a property is either a DatatypeProperty or an ObjectProperty.
Defaults to `None` (unknown).
:param domains: Set of class IRIs that are declared as the RDFS domain of the property. Defaults to `set()`.
:param ranges: Set of class IRIs that are declared as the RDFS range of the property. Defaults to `set()`.
"""
def __init__(self, manager, property_iri, supporter_class_iri, is_required=False, read_only=False,
write_only=False, cardinality=None, property_type=None,
write_only=False, reversed=False, cardinality=None, property_type=None,
domains=None, ranges=None):
self._logger = logging.getLogger(__name__)
self._manager = manager
Expand All @@ -49,6 +57,7 @@ def __init__(self, manager, property_iri, supporter_class_iri, is_required=False
raise OMPropertyDefError(u"Property %s cannot be read-only and write-only" % property_iri)
self._read_only = read_only
self._write_only = write_only
self._reversed = reversed

# Temporary list, before creating attributes
self._tmp_attr_mds = []
Expand Down Expand Up @@ -98,6 +107,11 @@ def is_write_only(self):
"""`True` if the property cannot be accessed by regular end-users."""
return self._write_only

@property
def reversed(self):
"""`True` if the property is reversed (?o ?p ?s)."""
return self._reversed

def declare_is_required(self):
"""Makes the property be required. Is irreversible."""
self._is_required = True
Expand Down Expand Up @@ -158,22 +172,23 @@ def om_attributes(self):
return self._om_attributes

def add_attribute_metadata(self, name, jsonld_type=None, language=None, container=None,
reverse=None):
reversed=False):
"""Adds metadata about a future :class:`~oldman.attribute.OMAttribute` object.
:param name: JSON-LD term representing the attribute.
:param jsonld_type: JSON-LD type (datatype IRI or JSON-LD keyword). Defaults to `None`.
:param language: Defaults to `None`.
:param container: JSON-LD container (`"@set"`, `"@list"`, `"@language"` or `"@index"`).
Defaults to `None`.
:param reverse: `True` if the object and subject in RDF triples should be reversed.
Defaults to `None`. Not yet supported.
:param reversed: `True` if the object and subject in RDF triples should be reversed.
Defaults to `False`.
"""
#TODO: support:
# - the container variable
# - reverse property
if self._om_attributes:
raise OMAlreadyGeneratedAttributeError(u"It is too late to add attribute metadata")

if self._reversed is not reversed:
raise OMInternalError(u"The property %s or the attribute %s is reversed while the latter is not"
% (self._iri, name))
if jsonld_type:
if jsonld_type == "@id":
self.type = OBJECT_PROPERTY
Expand All @@ -199,7 +214,7 @@ def add_attribute_metadata(self, name, jsonld_type=None, language=None, containe
raise OMInternalError(u"Multiple attribute named %s" % name)

self._tmp_attr_mds.append(OMAttributeMetadata(name, self, language, jsonld_type, container,
bool(reverse)))
reversed))

def generate_attributes(self, attr_format_selector):
"""Generates its :class:`~oldman.attribute.OMAttribute` objects.
Expand Down
7 changes: 6 additions & 1 deletion tests/default_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,19 @@
{
"property": "rel:parentOf"
},
{
"property": "rel:parentOf",
"hydra:reversed": True
},
{
"property": "cert:key"
},
{
"property": "wot:hasKey"
},
{
"property": "schema:employee"
"property": "schema:employee",
"hydra:reversed": True
}
]
}
Expand Down

0 comments on commit f2a76b6

Please sign in to comment.