Source code for schema_automator.annotators.jsonld_annotator
import json
import logging
from typing import Union, Dict, Optional
from linkml_runtime import SchemaView
from linkml_runtime.linkml_model import SchemaDefinition, Definition, Prefix, DefinitionName
from schema_automator.annotators import SchemaAnnotator
JSON = Dict
def is_url(s: str) -> bool:
if s is not None:
return s.startswith('http')
else:
return False
[docs]
class JsonLdAnnotator(SchemaAnnotator):
"""
Annotates a schema using URIs/Prefixes derived from a JSON-LD file
"""
[docs]
def annotate(self, schema: Union[str, SchemaDefinition], jsonld_path: str) -> SchemaDefinition:
"""
Annotate a schema
:param schema: schema object (mutated) or path to schema
:param jsonld_path: path to input JSONLD context file
:return:
"""
sv = SchemaView(schema)
with open(jsonld_path) as f:
jsonld = json.load(f)
ctxt = jsonld['@context']
for c in sv.all_classes().values():
self.annotate_element(c, 'class_uri', ctxt)
for s in sv.all_slots().values():
self.annotate_element(s, 'slot_uri', ctxt)
all_curies = []
for c in sv.all_classes().values():
if c.class_uri:
all_curies.append(c.class_uri)
for s in sv.all_slots().values():
if s.slot_uri:
all_curies.append(s.slot_uri)
all_prefixes = set()
for cu in all_curies:
all_prefixes.add(cu.split(':')[0])
print(f'ALL PREFIXES: {all_prefixes}')
for k, v in ctxt.items():
if k in all_prefixes:
if k not in schema.prefixes:
url = None
if isinstance(v, str):
url = v
if is_url(url):
schema.prefixes[k] = Prefix(k, url)
return schema
[docs]
def annotate_element(self, el: Definition, mapping_slot: str, jsonld: JSON):
if el.name in jsonld:
curie = self.get_curie(el.name, jsonld)
if curie:
logging.info(f'ANNOTATING: {el.name} with {curie}')
setattr(el, mapping_slot, curie)
else:
logging.error(f'Cannot annotate: {el.name}')
def get_curie(self, name: DefinitionName, jsonld: JSON) -> Optional[str]:
if name in jsonld:
curie = jsonld[name]
if isinstance(curie, str):
if curie.startswith('@'):
return None
else:
return curie
elif isinstance(curie, dict):
if '@id' in curie:
return curie['@id']