def _predicate(self, name: SlotDefinitionName) -> IRIREF: slot = self.schema.slots[name] if slot.mappings: return IRIREF(cu.expand_uri(slot.mappings[0])) else: # TODO: look at the RDF to figure out what URI's go here return IRIREF(BIOENTITY[underscore(name)])
def test_predicate_scan(self): c = setup_context(shex_1, rdf_1) predicates: List[URIRef] = [] c.visit_shapes( c.shapeExprFor(IRIREF('http://schema.example/UserShape')), triple_expr_finder, predicates) self.assertEqual([RDF.type], predicates) # Quick test of the utility function self.assertEqual( predicates_in_expression( c.shapeExprFor(IRIREF('http://schema.example/UserShape')), c), [ShExJ.IRIREF(str(u)) for u in predicates])
def evaluate(g: Graph, schema: Union[str, ShExJ.Schema], focus: Optional[Union[str, URIRef, IRIREF]], start: Optional[Union[str, URIRef, IRIREF, START, START_TYPE]] = None, debug_trace: bool = False) -> Tuple[bool, Optional[str]]: """ Evaluate focus node `focus` in graph `g` against shape `shape` in ShEx schema `schema` :param g: Graph containing RDF :param schema: ShEx Schema -- if str, it will be parsed :param focus: focus node in g. If not specified, all URI subjects in G will be evaluated. :param start: Starting shape. If omitted, the Schema start shape is used :param debug_trace: Turn on debug tracing :return: None if success or failure reason if failure """ if isinstance(schema, str): schema = SchemaLoader().loads(schema) if schema is None: return False, "Error parsing schema" if not isinstance(focus, URIRef): focus = URIRef(str(focus)) if start is None: start = str(schema.start) if schema.start else None if start is None: return False, "No starting shape" if not isinstance( start, IRIREF) and start is not START and start is not START_TYPE: start = IRIREF(str(start)) cntxt = Context(g, schema) cntxt.debug_context.debug = debug_trace map_ = FixedShapeMap() map_.add(ShapeAssociation(focus, start)) test_result, reasons = isValid(cntxt, map_) return test_result, '\n'.join(reasons)
def end_class(self, cls: ClassDefinition) -> None: if cls.is_a: self._add_constraint(self.namespaces.uri_for(camelcase(cls.is_a) + "_t")) for mixin in cls.mixins: if self._class_has_expressions(mixin): self._add_constraint(self.namespaces.uri_for(camelcase(mixin) + "_t")) if cls.name in self.synopsis.applytorefs: for applyto in self.synopsis.applytorefs[cls.name].classrefs: if self._class_has_expressions(applyto): self._add_constraint(self.namespaces.uri_for(camelcase(applyto) + '_t')) self.shape.closed = True self.shape.extra = [RDF.type] if self.shape.expression: # TODO: Figure out how to label a single triple expression if isinstance_(self.shape.expression, tripleExprLabel): self.shape.expression = EachOf(expressions=[self.shape.expression, wildcard(None)]) self.shape.expression.id = self.namespaces.uri_for(camelcase(cls.name) + "_t") else: self.shape.expression = wildcard(self.namespaces.uri_for(camelcase(cls.name) + "_t")) if self.class_identifier(cls): self.shape.extra = [RDF.type] type_constraint = TripleConstraint() type_constraint.predicate = RDF.type type_constraint.valueExpr = NodeConstraint(values=[IRIREF(self.namespaces.uri_for(cls.class_uri))]) if not self.shape.expression: self.shape.expression = type_constraint else: self.shape.expression = EachOf(expressions=[self.shape.expression, type_constraint]) shapeExpr = self.shape shapeExpr.id = self._shape_iri(cls.name) self.shapes.append(shapeExpr)
def visit_class_slot(self, cls: ClassDefinition, aliased_slot_name: str, slot: SlotDefinition) -> None: constraint = TripleConstraint() # Juggling to get the constraint to be either a single triple constraint or an eachof construct if not self.shape.expression: self.shape.expression = constraint elif isinstance(self.shape.expression, TripleConstraint): self.shape.expression = EachOf( expressions=[self.shape.expression, constraint]) else: self.shape.expression.expressions.append(constraint) constraint.predicate = self._predicate(slot.name) # JSON-LD generates multi-valued entries as lists constraint.min = 1 if slot.primary_key or slot.required else 0 constraint.max = 1 if not slot.multivalued or self.collections else -1 # TODO: This should not be hard coded -- figure out where to go with it rng = IRIREF(META.SlotRangeTypes) if slot.range == 'anytype' else\ self._type_constraint(slot.range) if slot.range and slot.range not in self.schema.classes else\ self._shapeIRI(slot.range) name_base = ("XSD_" + self.grounded_slot_range(slot.range)) if isinstance( rng, NodeConstraint) else str(rng) constraint.valueExpr = self.gen_multivalued_slot(name_base, rng) \ if slot.multivalued and self.collections else rng
def gen_multivalued_slot(self, target_name_base: str, target_type: IRIREF) -> IRIREF: """ Generate a shape that represents an RDF list of target_type @param target_name_base: @param target_type: @return: """ list_shape_id = IRIREF(target_name_base + "__List") if list_shape_id not in self.list_shapes: list_shape = Shape(id=list_shape_id, closed=True) list_shape.expression = EachOf() expressions = [ TripleConstraint(predicate=RDF.first, valueExpr=target_type, min=0, max=1) ] targets = ShapeOr() targets.shapeExprs = [(NodeConstraint(values=[RDF.nil])), list_shape_id] expressions.append( TripleConstraint(predicate=RDF.rest, valueExpr=targets)) list_shape.expression.expressions = expressions self.shapes.append(list_shape) self.list_shapes.append(list_shape_id) return list_shape_id
def _type_constraint(self, rnge: Optional[str]) -> NodeConstraint: # TODO: missing type - string or '.'? if rnge in builtin_names: return NodeConstraint(datatype=IRIREF(XSD[rnge])) elif rnge in self.schema.types: return self._type_constraint(self.schema.types[rnge].typeof) else: return NodeConstraint()
def add_builtins(self): # TODO: At some point we should get rid of the hard-coded builtins and add a set of TypeDefinitions for builtin_valueset = NodeConstraint(id=META.Builtins, values=[IriStem(IRIREF(XSD))]) self.shex.shapes.append(builtin_valueset) range_type_choices = ShapeOr(id=META.SlotRangeTypes, shapeExprs=[BIOENTITY.TypeDefinition, BIOENTITY.ClassDefinition, META.Builtins]) self.shex.shapes.append(range_type_choices)
def _type_arc(self, target: URIorCURIE, opt: bool = False) -> TripleConstraint: return TripleConstraint( predicate=RDF.type, valueExpr=NodeConstraint( values=[IRIREF(self.namespaces.uri_for(target))]), min=0 if opt else 1)
def __init__(self, default_base: Optional[str] = None): ShExDocVisitor.__init__(self) self.context = ParserContext() self.context.base = IRIREF(default_base) if default_base else None
def _shapeIRI(name: ClassDefinitionName) -> IRIREF: return IRIREF(BIOENTITY[camelcase(name)])
def _shape_iri(self, name: ElementName) -> IRIREF: return IRIREF(self.base[camelcase(name)])