Example #1
0
def gather_rules(shacl_graph):
    """

    :param shacl_graph:
    :type shacl_graph: ShapesGraph
    :return:
    :rtype: [SHACLRule]
    """
    triple_rule_nodes = set(shacl_graph.subjects(RDF_type, SH_TripleRule))
    sparql_rule_nodes = set(shacl_graph.subjects(RDF_type, SH_SPARQLRule))
    overlaps = triple_rule_nodes.intersection(sparql_rule_nodes)
    if len(overlaps) > 0:
        raise RuleLoadError(
            "A SHACL Rule cannot be both a TripleRule and a SPARQLRule.",
            "https://www.w3.org/TR/shacl-af/#rules-syntax")
    used_rules = shacl_graph.subject_objects(SH_rule)
    ret_rules = defaultdict(list)
    for sub, obj in used_rules:
        try:
            shape = shacl_graph.lookup_shape_from_node(sub)
        except (AttributeError, KeyError):
            raise RuleLoadError(
                "The shape that rule is attached to is not a valid SHACL Shape.",
                "https://www.w3.org/TR/shacl-af/#rules-syntax")
        if obj in triple_rule_nodes:
            rule = TripleRule(shape, obj)
        elif obj in sparql_rule_nodes:
            rule = SPARQLRule(shape, obj)
        else:
            raise RuleLoadError(
                "when using sh:rule, the Rule must be defined as either a TripleRule or SPARQLRule.",
                "https://www.w3.org/TR/shacl-af/#rules-syntax")
        ret_rules[shape].append(rule)
    return ret_rules
Example #2
0
    def __init__(self, shape: 'Shape', rule_node: 'rdflib.term.Identifier', **kwargs):
        """

        :param shape:
        :type shape: Shape
        :param rule_node:
        :type rule_node: rdflib.term.Identifier
        """
        super(SPARQLRule, self).__init__(shape, rule_node, **kwargs)
        construct_nodes = set(self.shape.sg.objects(self.node, SH_construct))
        if len(construct_nodes) < 1:
            raise RuleLoadError("No sh:construct on SPARQLRule", "https://www.w3.org/TR/shacl-af/#SPARQLRule")
        self._constructs = []
        for c in construct_nodes:
            if not isinstance(c, Literal) or not (
                c.datatype == XSD_string or c.language is not None or isinstance(c.value, str)
            ):
                raise RuleLoadError(
                    "SPARQLRule sh:construct must be an xsd:string", "https://www.w3.org/TR/shacl-af/#SPARQLRule"
                )
            self._constructs.append(str(c.value))
        SPARQLQueryHelper = get_query_helper_cls()
        query_helper = SPARQLQueryHelper(self.shape, self.node, None, deactivated=self._deactivated)
        query_helper.collect_prefixes()
        self._qh = query_helper
Example #3
0
 def get_conditions(self):
     cond_nodes = list(self.shape.sg.graph.objects(self.node, SH_condition))
     conditions = []
     for c in cond_nodes:
         # check if this is a rdf:list
         test_me = list(self.shape.sg.graph.predicate_objects(c))
         first_nodes = list(self.shape.sg.graph.objects(c, RDF_first))
         if len(first_nodes) > 0:
             for c_item in self.shape.sg.graph.items(c):
                 try:
                     cond_shape = self.shape.sg.lookup_shape_from_node(c_item)
                 except (AttributeError, KeyError):
                     raise RuleLoadError(
                         "A SHACL Rule Condition must be an existing well-formed SHACL Shape.",
                         "https://www.w3.org/TR/shacl-af/#condition")
                 condition = SHACLRuleCondition(self, cond_shape)
                 conditions.append(condition)
         else:
             try:
                 cond_shape = self.shape.sg.lookup_shape_from_node(c)
             except (AttributeError, KeyError):
                 raise RuleLoadError(
                     "A SHACL Rule Condition must be an existing well-formed SHACL Shape.",
                     "https://www.w3.org/TR/shacl-af/#condition")
             condition = SHACLRuleCondition(self, cond_shape)
             conditions.append(condition)
     return conditions
Example #4
0
def gather_rules(
        shacl_graph: 'ShapesGraph') -> Dict['Shape', List['SHACLRule']]:
    """

    :param shacl_graph:
    :type shacl_graph: ShapesGraph
    :return:
    :rtype: Dict[Shape, List[SHACLRule]]
    """
    triple_rule_nodes = set(shacl_graph.subjects(RDF_type, SH_TripleRule))
    sparql_rule_nodes = set(shacl_graph.subjects(RDF_type, SH_SPARQLRule))
    if shacl_graph.js_enabled:
        from pyshacl.extras.js.rules import JSRule, SH_JSRule

        js_rule_nodes = set(shacl_graph.subjects(RDF_type, SH_JSRule))
        use_JSRule: Union[bool, Type] = JSRule
    else:
        use_JSRule = False
        js_rule_nodes = set()
    overlaps = triple_rule_nodes.intersection(sparql_rule_nodes)
    if len(overlaps) > 0:
        raise RuleLoadError(
            "A SHACL Rule cannot be both a TripleRule and a SPARQLRule.",
            "https://www.w3.org/TR/shacl-af/#rules-syntax",
        )
    overlaps = triple_rule_nodes.intersection(js_rule_nodes)
    if len(overlaps) > 0:
        raise RuleLoadError(
            "A SHACL Rule cannot be both a TripleRule and a JSRule.",
            "https://www.w3.org/TR/shacl-af/#rules-syntax",
        )
    overlaps = sparql_rule_nodes.intersection(js_rule_nodes)
    if len(overlaps) > 0:
        raise RuleLoadError(
            "A SHACL Rule cannot be both a SPARQLRule and a JSRule.",
            "https://www.w3.org/TR/shacl-af/#rules-syntax",
        )
    used_rules = shacl_graph.subject_objects(SH_rule)
    ret_rules = defaultdict(list)
    for sub, obj in used_rules:
        try:
            shape: Shape = shacl_graph.lookup_shape_from_node(sub)
        except (AttributeError, KeyError):
            raise RuleLoadError(
                "The shape that rule is attached to is not a valid SHACL Shape.",
                "https://www.w3.org/TR/shacl-af/#rules-syntax",
            )
        if obj in triple_rule_nodes:
            rule: SHACLRule = TripleRule(shape, obj)
        elif obj in sparql_rule_nodes:
            rule = SPARQLRule(shape, obj)
        elif use_JSRule and callable(use_JSRule) and obj in js_rule_nodes:
            rule = use_JSRule(shape, obj)
        else:
            raise RuleLoadError(
                "when using sh:rule, the Rule must be defined as either a TripleRule or SPARQLRule.",
                "https://www.w3.org/TR/shacl-af/#rules-syntax",
            )
        ret_rules[shape].append(rule)
    return ret_rules
Example #5
0
 def order(self):
     order_nodes = list(self.shape.sg.objects(self.node, SH_order))
     if len(order_nodes) < 1:
         return Decimal("0.0")
     if len(order_nodes) > 1:
         raise RuleLoadError(
             "A SHACL Rule can have only one sh:order property.",
             "https://www.w3.org/TR/shacl-af/#rules-order")
     order_node = next(iter(order_nodes))
     if not isinstance(order_node, Literal):
         raise RuleLoadError("A SHACL Rule must be a numeric literal.",
                             "https://www.w3.org/TR/shacl-af/#rules-order")
     return Decimal(order_node.value)