Warning:
This wiki has been archived and is now read-only.

Validation

From Permissions and Obligations Expression Working Group
Jump to: navigation, search

Contents

ODRL Validation

An ODRL Validator has been defined as "A system that checks the conformance of ODRL Policy expressions, including the cardinality of properties and if they are related to types of values as defined by the ODRL Information Model, and the Information Model's validation requirements".

The validation function performs several verifications evaluating whether the policies in a certain input document conform with the normative part of the specifications (ODRL Information Model)[1] and ODRL Vocabulary[2].

The validation function accepts as input a document with one ore more policies, plus additional information. The validation function gives a boolean output (valid/non-valid) and optionally a comment (explanation, warning, etc.).

In order to simplify the processing of the ODRL policies (validation, evaluation, or other operations) a first step of normalization is described in this document. The validator operates on normalized policies.


Terminology

  • Normalized Policy: a Policy which has been subject to the transformations described in the section below, in the specified order.
  • Compound Rule: a Rule which has more than Assigner, more than one Assignee, more than one Action or more than one Asset.
  • Irreducible Rule: a Rule with at most one Assigner, at most one Assignee, at most one Action, and at most one Asset.
  • Root-level Rule: a Rule which is directly related to a Policy (i.e. there exists a odrl:permission, odrl:obligation or odrl:prohibition binding the Policy and the Rule).
  • ODRL policy document: an RDF graph which at least one ODRL Policy, possibly with other triples (e.g. ex:myAsset odrl:hasPolicy ex:mypolicy .)

Normalization

The ODRL specification permits several ways of representing the same information. The normalization function performs a sequence of transformations to achieve a standard form. Each transformation accepts one or more policies and generates zero or more policies, but their global meaning does not change. Normalization steps:

N1. Internalization of parties and assets declared out of the policy

The transformation replicates external references to the Policy, to the Assignee or to the Assigner (through the odrl:hasPolicy, odrl:assignerOf and odrl:assigneeOf respectively), asserting that information within the Policy, i.e., new properties with odrl:target, odrl:assigner and odrl:assignee are created, where the subject is the referred Policy. Please note that more than one target, assigner or assignee can exits.

Example:

<http://odrlapi.appspot.com/samples/sample012>
    a odrl:Agreement ;   
    odrl:permission [
        a odrl:Permission ;
        odrl:target <http://example.com/asset:9898> ;
        odrl:action odrl:reproduce ;
        odrl:assignee _:Alice ;
    ] .
<http://odrlapi.appspot.com/samples/party000>
   a odrl:Party;
   odrl:assignerOf <http://odrlapi.appspot.com/samples/sample012> .

is transformed into:

<http://odrlapi.appspot.com/samples/sample012>
    a odrl:Agreement ;   
    odrl:assigner <http://odrlapi.appspot.com/samples/party000> ;
    odrl:permission [
        a odrl:Permission ;
        odrl:target <http://example.com/asset:9898> ;
        odrl:action odrl:reproduce ;
        odrl:assignee _:Alice ;
    ] .

One possible way of implementing this transformation is using SPARQL Queries. For example:

PREFIX odrl: <http://www.w3.org/ns/odrl/2/> 
#FIRST QUERY
DELETE { 
  ?party odrl:assignerOf ?policy .
}
INSERT { 
   ?policy odrl:assigner ?party . 
}
WHERE { 
   ?party  odrl:assignerOf ?policy .
} 
#SECOND QUERY
DELETE { 
  ?party odrl:assigneeOf ?policy .
}
INSERT { 
   ?policy odrl:assignee ?party . 
}
WHERE { 
   ?party  odrl:assigneeOf ?policy .
} 
#THIRD QUERY
DELETE { 
  ?asset odrl:hasPolicy ?policy .
}
INSERT { 
   ?policy odrl:target ?asset . 
}
WHERE { 
   ?asset odrl:hasPolicy ?policy .
}

See also IM Sections 2.2.3, 2.3.3.

N2. Type declaration of policy elements

This transformation asserts class types for individuals of Policy, Set, Permission, Duty, Constraint and LogicalConstraint whenever it can be inferred. Policy, Permission, Duty, Constraint can be directly inferred from the RDFS domain and range of properties in the ODRL Ontology.

Set can be deduced as per IM 2.1.1 "The Set Policy subclass is also the default subclass of Policy (if none is specified)". Equivalently, the individuals of Permission, Prohibition, Duty, Constraint and LogicalConstraint can be inferred. This step is still necessary even if an OWL reasoner is used to extract general inferred axioms, given the specific nature of the Set, which prevails when nothing else is said [3](default logic). LogicalConstraint cannot be directly deduced, but for the presence of logical constraints operators.

Example of transformation:

<http://odrlapi.appspot.com/samples/sample001>
    a odrl:Policy;
    odrl:permission [
        odrl:target <http://odrlapi.appspot.com/samples/asset000> ;
        odrl:action odrl:reproduce
    ] .

is transformed into:

<http://odrlapi.appspot.com/samples/sample001>
    a odrl:Policy, odrl:Set;
    odrl:permission [
        a odrl:Permission ;
        odrl:target <http://odrlapi.appspot.com/samples/asset000> ;
        odrl:action odrl:reproduce
    ] .

N3. Application of inheritance rules

This transformation applies the inheritance rules defined IM Section 2.9. The transformation is necessary because a non-valid Policy may become valid upon application of these rules.

Given a set of policies (instances of Policy), this step applies the inheritance mechanism making the policies self-contained (i.e. after this step no inheritsFrom exists in the set of policies). The set of policies and their relations constitutes an acyclic directed graph, and it can be traversed in topological order so that every inheritance transformations is made in the correct order (see Kahn's or DFS algorithms). The original triple with inheritFrom is removed in this transformation (or moved to a metadata property).

<http://odrlapi.appspot.com/samples/sample045>
    odrl:assigner <http://example.com/org-01> ;
    odrl:obligation [
        odrl:target <http://example.com/asset:terms-and-conditions> ;
        odrl:action odrl:reviewPolicy
    ] .
<http://odrlapi.appspot.com/samples/sample045b>
    a odrl:Agreement ;
    odrl:inheritFrom <http://odrlapi.appspot.com/samples/sample045> ;
    odrl:assignee <http://example.com/user:0001> ;
    odrl:permission [
        odrl:target <http://example.com/asset:555> ;
        odrl:action odrl:display
    ] .

is transformed into:

<http://odrlapi.appspot.com/samples/sample045>
    odrl:assigner <http://example.com/org-01> ;
    odrl:obligation [
        odrl:target <http://example.com/asset:terms-and-conditions> ;
        odrl:action odrl:reviewPolicy
    ] .
<http://odrlapi.appspot.com/samples/sample045b>
    a odrl:Agreement ;
    odrl:assignee <http://example.com/user:0001> ;
    odrl:permission [
        odrl:target <http://example.com/asset:555> ;
        odrl:action odrl:display
    ]  ;
    odrl:assigner <http://example.com/org-01> ;
    odrl:obligation [
        odrl:target <http://example.com/asset:terms-and-conditions> ;
        odrl:action odrl:reviewPolicy
    ] .

See also IM Section 2.9.

N4. Interiorizing policy-level properties

This transformation adds the policy-level properties to each of the root Rules and removes them from the Policy level. Root rules are Rules directly related to the Policy and not in a second level. Examples of Rule in a second level are: a Duty of a permission, failure, consequences or remedies. Example of transformation:

<http://odrlapi.appspot.com/samples/sample001x>
    odrl:target <http://odrlapi.appspot.com/samples/asset000> ;
    odrl:permission [
        odrl:action odrl:reproduce
    ];
    odrl:prohibition[
        odrl:action odrl:print
    ] .

becomes:

<http://odrlapi.appspot.com/samples/sample001x>
    odrl:permission [
        odrl:action odrl:reproduce ;
        odrl:target <http://odrlapi.appspot.com/samples/asset000> 
    ];
    odrl:prohibition[
        odrl:action odrl:print ;
        odrl:target <http://odrlapi.appspot.com/samples/asset000> 
    ] .

See also IM Section 2.7.1.

N5. Expansion from compound to irreducible rules

This transformation expands any compound Rule (with two or more Assets, Assigners, Assignees or Actions) into a set of Rules each of them with at most one of these elements. The Policy Rule Composition in the IM describes accurately how to make this transformation. Example of this transformation:

<http://odrlapi.appspot.com/samples/sample070>
    odrl:permission [
        odrl:target <http://example.com/music/1999.mp3>, <http://example.com/music/PurpleRain.mp3> ;
        odrl:assigner <http://example.com/org/sony-music> ;
        odrl:action odrl:play, odrl:stream
    ] .

becomes:

<http://odrlapi.appspot.com/samples/sample070>
    odrl:permission [
        odrl:target <http://example.com/music/1999.mp3> ;
        odrl:assigner <http://example.com/org/sony-music> ;
        odrl:action odrl:play
    ], [
        odrl:target <http://example.com/music/1999.mp3>;
        odrl:assigner <http://example.com/org/sony-music> ;
        odrl:action odrl:stream
    ], [
        odrl:target <http://example.com/music/PurpleRain.mp3> ;
        odrl:assigner <http://example.com/org/sony-music> ;
        odrl:action odrl:play
    ], [
        odrl:target <http://example.com/music/PurpleRain.mp3> ;
        odrl:assigner <http://example.com/org/sony-music> ;
        odrl:action odrl:stream
    ] .

See also IM Section 2.7

N6. Inferences derived from odrl:includedIn

This transformation transforms every Rule including the action β by adding the property-value odrl:action α for every α where α odrl:includedIn β .

If an Action α is included in another Action β (α odrl:includedIn β .), all Rules defined for β must also hold for α, but not necessarily vice versa.

Example of this transformation:

odrl:play odrl:includedIn odrl:use . 
odrl:display odrl:includedIn odrl:use . 
odrl:print odrl:includedIn odrl:use .

<http://odrlapi.appspot.com/samples/sample078>
    a odrl:Policy;
    odrl:permission [
        a odrl:Permission ;
        odrl:target ex:PartA ;
        odrl:action odrl:use ;
        odrl:assignee ex:Bob
    ] ;
    odrl:prohibition [
        a odrl:Prohibition ;
        odrl:target ex:PartB ;
        odrl:action odrl:print ;
        odrl:assignee ex:Bob
    ] .

becomes

<http://odrlapi.appspot.com/samples/sample078>
    a odrl:Policy;
    odrl:permission [
        a odrl:Permission ;
        odrl:target ex:PartA ;
        odrl:action odrl:use ;
        odrl:action odrl:play ; 
        odrl:action odrl:display; 
        odrl:action odrl:print ; 
        odrl:assignee ex:Bob
    ] ;
    odrl:prohibition [
        a odrl:Prohibition ;
        odrl:target ex:PartB ;
        odrl:action odrl:print ;
        odrl:assignee ex:Bob
    ] .

See also https://www.w3.org/2016/poe/wiki/Policy_Inference

N7. Inferences derived from odrl:implies

This transformation transforms every Permission or Duty including the action α by adding the property-value odrl:action β for every α where α odrl:implies β .

If an Action α implies another Action β (α odrl:implies β), a Prohibition of β conflicts a Permission of α, but not necessarily vice versa (i.e., a Prohibition of α is not in conflict with a Permission of β).

As an example of this transformation, the following ODRL Policy Document...

odrl:share odrl:implies odrl:distribute . 
odrl:move odrl:implies odrl:delete . 

<http://odrlapi.appspot.com/samples/sample079>
    a odrl:Policy;
    odrl:permission [
        a odrl:Permission ;
        odrl:target ex:PartA ;
        odrl:action odrl:share ;
        odrl:assignee ex:Bob
    ] ;
    odrl:prohibition [
        a odrl:Prohibition ;
        odrl:target ex:PartB ;
        odrl:action odrl:move ;
        odrl:assignee ex:Bob
    ] .

becomes

<http://odrlapi.appspot.com/samples/sample079>
    a odrl:Policy;
    odrl:permission [
        a odrl:Permission ;
        odrl:target ex:PartA ;
        odrl:action odrl:share ;
        odrl:action odrl:distribute ; 
        odrl:assignee ex:Bob
    ] ;
    odrl:prohibition [
        a odrl:Prohibition ;
        odrl:target ex:PartB ;
        odrl:action odrl:move ;
        odrl:assignee ex:Bob
    ] .

See also https://www.w3.org/2016/poe/wiki/Policy_Inference

N8. Inferences derived from odrl:partOf for Asset Collection

This transformation changes every Rule including the Asset β with the property odrl:target by adding the property-value odrl:target α for every α where

α odrl:partOf β .

Example of this transformation:

ex:Part1 odrl:partOf ex:Dataset . 
ex:Part2 odrl:partOf ex:Dataset . 

<http://odrlapi.appspot.com/samples/sample080>
    a odrl:Policy;
    odrl:permission [
        a odrl:Permission ;
        odrl:target ex:Dataset ;
        odrl:action odrl:use ;
        odrl:assignee ex:Bob
    ] .

becomes

ex:Part1 odrl:partOf ex:Dataset . 
ex:Part2 odrl:partOf ex:Dataset . 

<http://odrlapi.appspot.com/samples/sample080>
    a odrl:Policy;
    odrl:permission [
        a odrl:Permission ;
        odrl:target ex:Dataset ;
        odrl:target ex:Part1 ;
        odrl:target ex:Part2 ;
        odrl:action odrl:use ;
        odrl:assignee ex:Bob
    ] .

See also https://www.w3.org/2016/poe/wiki/Policy_Inference

N9. Inferences derived from odrl:partOf for Party Collection

This transformation changes every Rule including the Party Collection β by adding an additional Rule with the explicit (known) members of the Party Collection .

Example of this transformation:

ex:Person1 odrl:partOf ex:Team . 
ex:Person2 odrl:partOf ex:Team . 

<http://odrlapi.appspot.com/samples/sample081>
    a odrl:Policy;
    odrl:permission [
        a odrl:Permission ;
        odrl:target ex:Dataset ;
        odrl:action odrl:use ;
        odrl:assignee ex:Team
    ] .

becomes

ex:Person1 odrl:partOf ex:Team. 
ex:Person2 odrl:partOf ex:Team . 

<http://odrlapi.appspot.com/samples/sample081>
    a odrl:Policy;
     odrl:permission [
        a odrl:Permission ;
        odrl:target ex:Dataset ;
        odrl:action odrl:use ;
        odrl:assignee ex:Team, ex:Person1, ex:Person2
    ] .

See also https://www.w3.org/2016/poe/wiki/Policy_Inference

N10. Policy Replacement

This transformation affects every policy α if the following triple exists: α odrl:isReplacedBy β .

The transformation consists of two changes:

  • every rule of α must be removed.
  • If the policy β is identified by a dereferenceable URI, the policy is obtained and its rules are added to α.

The example below shows Policy sample099 is replaced by Policy sample005.

<http://odrlapi.appspot.com/samples/sample082>
    a odrl:Policy ;
    dc:isReplacedBy <http://odrlapi.appspot.com/samples/sample005> ;
    odrl:permission [
        odrl:target <http://example.com/asset:555> ;
        odrl:action odrl:display
    ] .

becomes:

<http://odrlapi.appspot.com/samples/sample082>
    a odrl:Policy;
    odrl:permission [
        a odrl:Permission ;
        odrl:target "asset9898" ;
        odrl:action odrl:reproduce
    ] .

Please note that the policy <http://odrlapi.appspot.com/samples/sample005> is actually dereferenceable.

Order of transformations

The correct order for the transformations would be N1, N2, N3, N10, N4, N6, N7, N8, N9, N5. Pending to be renamed after after no references are found.

Validation

The validation function can be implemented as a sequence of individual validation operations. The order of the validation operations is irrelevant. The result of each validation operation can be either true or false.

The validation function takes one or more Policies as input. The following validation operations have been described:

V1. A valid document must contain at least one Policy

The validator must find at least one Policy. This is not a validation in the specs, but rather a meta-validation. Validations not considering the Transformation2 defined above would not consider the following Policy as such and may issue a warning. Example of document that will not be validated if transformations are not done.

<http://example.org/policy/1> odrl:permission [
  odrl:target <http://example.com/asset/1> ;
  odrl:assignee <http://example.com/party/Alice> ;
  odrl:action odrl:use
] ;

V2. Every policy must have at least one rule

Every Policy must have at least one Rule, related to the Policy through one of the properties; odrl:permission, odrl:prohibition, or odrl:obligation. Example of invalid Policy:

<http://odrlapi.appspot.com/samples/sample002>
    a odrl:Policy .

SHACL Shape:

odrl:PolicyShape
    a sh:NodeShape ;
    sh:targetClass odrl:Policy ;
    sh:property [
        sh:path [ 
            sh:alternativePath ( odrl:permission odrl:prohibition odrl:obligation ) 
        ] ;
        sh:minCount 1 ;
    ] .

V3. Every policy must be identified by a URI

Every Policy must be identified by a URI. Example of invalid Policy:

[] odrl:permission [
  odrl:target <http://example.com/asset/1> ;
  odrl:assignee <http://example.com/party/Alice> ;
  odrl:action odrl:use
] ;

SHACL Shape:

odrl:PolicyShape
    a sh:NodeShape ;
    sh:targetClass odrl:Policy ;
    sh:nodeKind sh:IRI .

V4. Every rule in an offer must have exactly one assigner

After normalization, every Rule in an Offer must have exactly one Assigner. Example of invalid Policy:

<http://odrlapi.appspot.com/samples/sample006>
    a odrl:Offer ;   
    dct:source <https://github.com/simonstey/ODRL-SHACL-Shapes/wiki/3.1.3-Offer> ;
    odrl:permission [
        a odrl:Permission ;
        odrl:target <http://example.com/asset:9898> ;
        odrl:action odrl:reproduce ;
    ] .

SHACL Shape:

odrl:OfferShape
    a sh:NodeShape ;
    sh:targetClass odrl:Offer ;
    sh:property [
        sh:path [ 
            sh:alternativePath ( odrl:permission odrl:prohibition odrl:obligation ) 
        ] ;
        sh:node odrl:assignerMinShape ;
    ] .

odrl:assignerMinShape
    a sh:NodeShape ;
    sh:property [
        sh:path odrl:assigner ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
    ] .

V5. Every rule in an agreement must have exactly one assigner

After normalization, every Rule in one Agreement must have exactly one Assigner Example of invalid Policy:

<http://odrlapi.appspot.com/samples/sample006x>
    a odrl:Agreement ;   
    dct:source <https://github.com/simonstey/ODRL-SHACL-Shapes/wiki/3.1.3-Offer> ;
    odrl:permission [
        a odrl:Permission ;
        odrl:target <http://example.com/asset:9898> ;
        odrl:assignee <http://example.com/me> ;
        odrl:action odrl:reproduce ;
    ] .

SHACL Shape:

odrl:AgreementShape
    a sh:NodeShape ;
    sh:targetClass odrl:Agreement ;
    sh:property [
        sh:path [ 
            sh:alternativePath ( odrl:permission odrl:prohibition odrl:obligation ) 
        ] ;
        sh:node odrl:assignerMinShape ;
        sh:node odrl:assigneeMinShape ;
    ] .

odrl:assignerMinShape
    a sh:NodeShape ;
    sh:property [
        sh:path odrl:assigner ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
    ] .
	
odrl:assigneeMinShape
    a sh:NodeShape ;
    sh:property [
        sh:path odrl:assignee ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
    ] .

V6. Every rule in an agreement must have exactly one assignee

After normalization, every Rule in one Agreement must have exactly one Assignee. NOTE. Please note that this validation rule is compromising: cannot be understood without normalization. That is to say, normalization must be normative parte of the validation. Example of invalid Policy:

<http://odrlapi.appspot.com/samples/sample006xx>
    a odrl:Agreement ;   
    dct:source <https://github.com/simonstey/ODRL-SHACL-Shapes/wiki/3.1.3-Offer> ;
    odrl:permission [
        a odrl:Permission ;
        odrl:target <http://example.com/asset:9898> ;
        odrl:assigner <http://example.com/me> ;
        odrl:action odrl:reproduce ;
    ] .

V7. Every rule must have exactly one target

After normalization, every Rule in a Policy must have exactly one Target. Please note that this validation rule is tremendously compromising: cannot be understood without normalization. That is to say, normalization must be normative part of the validation. Example of invalid policy:

<http://odrlapi.appspot.com/samples/sample006xxx>
    a odrl:Agreement ;   
    odrl:permission [
        a odrl:Permission ;
        odrl:target <http://example.com/asset:9898>, <http://example.com/asset:9899>;
        odrl:assigner <http://example.com/me> ;
        odrl:action odrl:reproduce ;
    ] .

SHACL Shape:

odrl:PolicyShape
    a sh:NodeShape ;
    sh:targetClass odrl:Policy ;
    sh:property [
        sh:path [ 
            sh:alternativePath ( odrl:permission odrl:prohibition ) 
        ] ;
        sh:node odrl:targetCardShape ;
    ] .
 
odrl:targetCardShape 
    a sh:NodeShape ;
    sh:property [
        sh:path odrl:target ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
    ] .

V8. No remedy can refer to a duty that includes a consequence duty

A Remedy must not refer to a Duty that includes a consequence Duty (IM 2.6.7). Example of invalid Policy:

<http://odrlapi.appspot.com/samples/sample073>
    a odrl:Agreement ;
    odrl:profile <http://example.com/odrl:profile:09> ;
    odrl:prohibition [
        odrl:target <http://example.com/data:77> ;
        odrl:assigner <http://example.com/person:88> ;
        odrl:assignee <http://example.com/person:99> ;
        odrl:action odrl:modify ;
        odrl:remedy [
            odrl:action odrl:delete ;
            odrl:target <http://example.com/data:77> ;
            odrl:consequence [
                odrl:action odrl:acceptTracking ;
                odrl:trackingParty <http://example.com/dept:100> ;
                odrl:constraint [
                    odrl:leftOperand odrl:dateTime ;
                    odrl:operator odrl:lteq;
                    odrl:rightOperand "2017-12-31"
                ]
            ]
        ]
    ] .

SHACL Shape:

odrl:RemedyShape
    a sh:NodeShape ;
    sh:targetObjectsOf odrl:remedy ;                  
    sh:property [
        sh:path odrl:consequence ;
        sh:maxCount 0 ;
    ] .

V9. Every AssetCollection with a refinement must have a source

Every AssetCollections with a property odrl:refinement must have a property odrl:source. Example of invalid Policy:

<http://odrlapi.appspot.com/samples/sample065x>
    a odrl:Offer ;
    odrl:permission [
        odrl:assigner <http://example.com/org88> ;
        odrl:action odrl:play ;
        odrl:target [
            a odrl:AssetCollection ;
            ## odrl:source <http://example.com/media-catalogue> ;
            odrl:refinement [
                odrl:leftOperand odrl:runningTime ;
                odrl:operator odrl:lt ;
                odrl:rightOperand 60 ;
                odrl:unit <http://qudt.org/vocab/unit/MinuteTime>
            ]
        ]
    ] .

SHACL Shape:

odrl:AssetCollectionShape
    a sh:NodeShape ;
    sh:targetClass odrl:AssetCollection ;
	sh:xone ( odrl:WithRefinementShape odrl:WithoutRefinementShape ) .

odrl:WithRefinementShape
    a sh:NodeShape ;
    sh:property [
        sh:path odrl:source ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
    ] ;
    sh:property [
        sh:path odrl:refinement ;
        sh:minCount 1 ;
    ] .	
	
odrl:WithoutRefinementShape
    a sh:NodeShape ;
    sh:property [
        sh:path odrl:source ;
        sh:maxCount 0 ;
    ] ;
    sh:property [
        sh:path odrl:refinement ;
        sh:maxCount 0 ;
    ] .

V10. Every PartyCollection with a refinement must have a odrl:source

Every PartyCollection with a property odrl:refinement must have a property odrl:source. Example of invalid Policy:

<http://odrlapi.appspot.com/samples/sample067x>
    a odrl:Agreement ;
    dct:source "http://w3c.github.io/poe/model/";
    odrl:profile <http://example.com/odrl:profile:12> ;
    odrl:permission [
        odrl:assigner <http://example.com/user44> ;
        odrl:target <http://example.com/myPhotos:BdayParty> ;
        odrl:action odrl:display ;
        odrl:assignee [
            a odrl:PartyCollection ;
 ##         odrl:source <http://example.com/user44/friends> ;
            odrl:refinement [
                odrl:leftOperand foaf:age ;
                odrl:operator odrl:gt ;
                odrl:rightOperand 17 ;
            ]
        ]
    ] .

SHACL Shape:

odrl:PartyCollectionShape
    a sh:NodeShape ;
    sh:targetClass odrl:PartyCollection ;
    sh:xone ( odrl:WithRefinementShape odrl:WithoutRefinementShape ) .

odrl:WithRefinementShape
    a sh:NodeShape ;
    sh:property [
        sh:path odrl:source ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
    ] ;
    sh:property [
        sh:path odrl:refinement ;
        sh:minCount 1 ;
    ] .	
	
odrl:WithoutRefinementShape
    a sh:NodeShape ;
    sh:property [
        sh:path odrl:source ;
        sh:maxCount 0 ;
    ] ;
    sh:property [
        sh:path odrl:refinement ;
        sh:maxCount 0 ;
    ] .

V11. In absence of profile, only ODRL Core conflict strategies can be used

If no profile is given, then unknown conflict strategies cannot be used. Example of invalid Policy:

<http://odrlapi.appspot.com/samples/sample063x>
    a odrl:Policy;
    ## odrl:profile <http://example.com/odrl:profile:40> ;
    odrl:conflict <http://example.com/odrl/profile/40/strategyUNKNOWN> ;
    odrl:permission [
        a odrl:Permission ;
        odrl:target <http://example.com/asset:1212> ;
        odrl:action odrl:use ;
        odrl:assigner <http://example.com/owner:181> 
    ] .

V12. In absence of profile, only ODRL actions can be used

If no profile is given, unknown Actions cannot be used. ODRL actions are the actions defined in the ODRL Core Model plus in the ODRL Vocabulary. Actions have to be verified either from their URI or from their rdf:value when necessary. Example of invalid Policy:

<http://odrlapi.appspot.com/samples/sample057x>
    odrl:permission [
        odrl:target <http://odrlapi.appspot.com/samples/asset000> ;
        odrl:action p1:supercalifragilisticoespialidoso
    ] .

V13. In absence of profile, only ODRL left operands can be used

If no profile is given, unknown LeftOperands (odrl:leftOperand) cannot be given Example of invalid Policy:

<http://odrlapi.appspot.com/samples/sample058x>
    a odrl:Policy;
    odrl:permission [
        a odrl:Permission ;
        odrl:target <http://odrlapi.appspot.com/samples/asset000> ;
        odrl:action odrl:play
        odrl:constraint [
            odrl:leftOperand p1:abracadabra ;
            odrl:operator odrl:lteq;
            odrl:rightOperand "2017-12-31"
        ]  
    ] .

V14. In absence of profile, only ODRL operators can be used

If no profile is given, unknown operators (odrl:operator) cannot be given. Example of invalid Policy:

<http://odrlapi.appspot.com/samples/sample058xx>
    a odrl:Policy;
    odrl:permission [
        a odrl:Permission ;
        odrl:target <http://odrlapi.appspot.com/samples/asset000> ;
        odrl:action odrl:play
        odrl:constraint [
            odrl:leftOperand odrl:dateTime;
            odrl:operator p1:abracadabra;
            odrl:rightOperand "2017-12-31"
        ]  
    ] .

V15. In absence of profile, only ODRL logical constraints can be used

If no profile is given, unknown LogicalConstraints cannot be given. Every LogicalConstraint must have either one of {odrl:or, odrl:xone, odrl:and, odrl:andSequence} or a profile must be referenced. Example of invalid Policy:

<http://odrlapi.appspot.com/samples/sample053>
    a odrl:Set ;
    odrl:permission [
        odrl:target <http://example.com/book/1999> ;
        odrl:assigner <http://example.com/org/paisley-park> ;
        odrl:action odrl:play ;
        odrl:constraint [
            p1:nand <http://example.com/p:88/C1> ;
        ]    
   ] .

V16. Every constraint must have exactly one right operand

Every Constraint must have exactly one right operand odrl:rightOperand. Because the values can be both literals and IRIs, no further validations are made on the value's class. Example of invalid Policy:

<http://odrlapi.appspot.com/samples/sample069x>
    a odrl:Agreement ;
    odrl:profile <http://example.com/odrl:profile:09> ;
    odrl:assigner <http://example.com/org:43> ;
    odrl:assignee <http://example.com/person:44> ;
    odrl:obligation [
        odrl:target <http://example.com/document:XZY> ;
        odrl:action odrl:delete ;
        odrl:consequence [
            odrl:action [
                rdf:value odrl:compensate ;
                odrl:compensatedParty <http://wwf.org> ;
                odrl:refinement [
                    odrl:leftOperand odrl:payAmount ;
                    odrl:operator odrl:eq ;
                    ## odrl:rightOperand 10.00 ;
                    odrl:unit <http://dbpedia.org/resource/Euro> 
                ]
            ]
        ] 
    ] .

SHACL Shape:

odrl:RightOperandShape
    a sh:NodeShape ;
    sh:targetClass odrl:Constraint ;  
    sh:xone ( odrl:rightOperandSingleShape odrl:rightOperandRefShape ) .

odrl:rightOperandSingleShape
    a sh:NodeShape ;          
    sh:property [
        sh:path odrl:rightOperand ;
        sh:minCount 1 ;
    ] .

odrl:rightOperandRefShape 
    a sh:NodeShape ;          
    sh:property [
        sh:path odrl:rightOperandReference ;
        sh:minCount 1 ;
    ] .

V17. Every constraint must have exactly one left operand

Constraints must have exactly one leftOperand. Values of the leftOperand property must be instances of LeftOperand. Example of invalid policy:

<http://odrlapi.appspot.com/samples/sample069x>
    a odrl:Agreement ;
    odrl:profile <http://example.com/odrl:profile:09> ;
    odrl:assigner <http://example.com/org:43> ;
    odrl:assignee <http://example.com/person:44> ;
    odrl:obligation [
        odrl:target <http://example.com/document:XZY> ;
        odrl:action odrl:delete ;
        odrl:consequence [
            odrl:action [
                rdf:value odrl:compensate ;
                odrl:compensatedParty <http://wwf.org> ;
                odrl:refinement [
                    ##odrl:leftOperand odrl:payAmount ;
                    odrl:operator odrl:eq ;
                    odrl:rightOperand 10.00 ;
                    odrl:unit <http://dbpedia.org/resource/Euro> 
                ]
            ]
        ] 
    ] .

SHACL Shape:

odrl:LeftOperandShape
    a sh:NodeShape ;
    sh:targetClass odrl:Constraint ;              
    sh:property [
        sh:path odrl:leftOperand ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:class odrl:LeftOperand ;
    ] .

V18. Every constraint must have exactly one operator

Every Constraint must have exactly one Operator. The operator property values are defined as instances of the Operator class. Example of invalid policy.

<http://odrlapi.appspot.com/samples/sample069xy>
    a odrl:Agreement ;
    odrl:profile <http://example.com/odrl:profile:09> ;
    odrl:assigner <http://example.com/org:43> ;
    odrl:assignee <http://example.com/person:44> ;
    odrl:obligation [
        odrl:target <http://example.com/document:XZY> ;
        odrl:action odrl:delete ;
        odrl:consequence [
            odrl:compensatedParty <http://wwf.org> ;
            odrl:action [
                rdf:value odrl:compensate ;
                odrl:refinement [
                    odrl:leftOperand odrl:payAmount ;
                    odrl:operator odrl:eq, odrl:lt ;
                    odrl:rightOperand 10.00 ;
                    odrl:unit <http://dbpedia.org/resource/Euro> 
                ]
            ]
        ] 
    ] .

SHACL Shape:

odrl:OperatorShape
    a sh:NodeShape ;
    sh:targetClass odrl:Constraint ;              
    sh:property [
        sh:path odrl:operator ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
    ] .

V19. The values of every logical constraint must be constraints

The values of every LogicalConstraint must be Constraints. Example of invalid Policy:

<http://odrlapi.appspot.com/samples/sample052x>
    a odrl:Offer ;
    odrl:profile <http://example.com/odrl:profile:10> ;
    odrl:permission [
        odrl:target <http://example.com/book/1999> ;
        odrl:assigner <http://example.com/org/paisley-park> ;
        odrl:action [
            rdf:value odrl:reproduce ;
            odrl:refinement [
                odrl:xone (<http://example.com/p:88/C1> <http://example.com/p:88/C2>)
            ]
        ]
   ] .
<http://example.com/p:88/C1> 
    a p1:NotAConstraint ;
    odrl:leftOperand odrl:media ;
    odrl:operator odrl:eq ;
    odrl:rightOperand odrl:online .
<http://example.com/p:88/C2> 
    a odrl:Constraint ;
    odrl:leftOperand odrl:media ;
    odrl:operator odrl:eq ;
    odrl:rightOperand odrl:print .

SHACL Shape:

odrl:LogicConstraintShape
    a sh:NodeShape ;
    sh:targetObjectsOf odrl:and ;         
    sh:targetObjectsOf odrl:or ;          
    sh:targetObjectsOf odrl:xone ;       
    sh:property [
        sh:path ( [ sh:zeroOrMorePath rdf:rest ] rdf:first ) ;
        sh:class odrl:Constraint ;
    ] .

V20. The values of the property rightOperandReference must be URIs

Values of the property rightOperandReference must be URIs. Example of invalid policy:

<http://odrlapi.appspot.com/samples/sample044x>
    a odrl:Offer ;
    odrl:profile <http://example.com/odrl:profile:07> ;
    odrl:permission [
        odrl:target <http://example.com/game:9090> ;
        odrl:assigner <http://example.com/org:xyz> ;
        odrl:action odrl:play ;
        odrl:constraint [
            odrl:leftOperand odrl:dateTime ;
            odrl:operator odrl:lteq;
            odrl:rightOperandReference "asdf" 
        ]            
    ] .

SHACL Shape:

odrl:RightOperandReferenceShape
    a sh:NodeShape ;
    sh:targetObjectsOf odrl:rightOperandReference ;
    sh:nodeKind sh:IRI .

V21. Every value of the property odrl:datatype must be of type rdfs:Datatype

Values of the property odrl:datatype must be of type rdfs:Datatype

<http://odrlapi.appspot.com/samples/sample044xx>
    a odrl:Offer ;
    odrl:profile <http://example.com/odrl:profile:07> ;
    odrl:permission [
        odrl:target <http://example.com/game:9090> ;
        odrl:assigner <http://example.com/org:xyz> ;
        odrl:action odrl:play ;
        odrl:constraint [
            odrl:leftOperand odrl:dateTime ;
            odrl:operator odrl:lteq;
            odrl:rightOperandReference <http://nogo.com> ;
            odrl:datatype p:NonRDFSDatatype;
             
        ]            
    ] .

SHACL Shape:

odrl:DatatypeShape
    a sh:NodeShape ;
    sh:targetObjectsOf odrl:datatype ;
    sh:class rdfs:Datatype .

V22. Every prohibition must be disjoint with permissions and obligations

A Rule cannot be Prohibition and Permission at the same time. A Rule cannot be Prohibition and Obligation at the same time. Example of invalid Policy:

<http://odrlapi.appspot.com/samples/sample051x>
    a odrl:Policy;
    odrl:permission [
        a odrl:Permission, odrl:Prohibition ;
        odrl:target <http://odrlapi.appspot.com/samples/asset000> ;
        odrl:action odrl:reproduce
    ] .

SHACL Shape:

odrl:ProhibitionShape
    a sh:NodeShape ;
    sh:targetClass odrl:Prohibition ;
    sh:not [
        a sh:NodeShape ;
        sh:class odrl:Permission ;
    ] ;
    sh:not [
        a sh:NodeShape ;
        sh:class odrl:Duty ;
    ] .

V23. Every policy most have at most one conflict strategy

There can be at most one conflict strategy (odrl:conflict). Example of invalid Policy:

<http://odrlapi.appspot.com/samples/sample051xxx>
    a odrl:Policy ;
    odrl:conflict odrl:perm, odrl:prohibit ;
    odrl:permission [
        a odrl:Permission, odrl:Prohibition ;
        odrl:target <http://odrlapi.appspot.com/samples/asset000> ;
        odrl:action odrl:reproduce
    ] .

SHACL Shape:

odrl:PolicyShape
    a sh:NodeShape ;
    sh:targetClass odrl:Policy ;
	sh:property [
        sh:path odrl:conflict ;
        sh:class odrl:ConflictTerm ;
        sh:maxCount 1 ;
    ] .

V24. No policy can inherit directly or indirectly from itself

Inheritance must not be circular. No Policy can inherit directly or indirectly from itself. The inheritance graph must be acyclic. Example of invalid Policy:

<http://odrlapi.appspot.com/samples/sample048>
    a odrl:Policy ;
    dct:source "victor" ;
    odrl:inheritFrom <http://odrlapi.appspot.com/samples/sample048b> ;
    odrl:target <http://example.com/asset:terms-and-conditions> ;
    odrl:obligation [
        odrl:action odrl:reviewPolicy
    ] .
<http://odrlapi.appspot.com/samples/sample048b>
    a odrl:Policy ;
    odrl:inheritFrom <http://odrlapi.appspot.com/samples/sample048c> ;
    odrl:permission [
        odrl:assigner <http://example.com/asset:555> ;
        odrl:action odrl:display
    ] .
<http://odrlapi.appspot.com/samples/sample048c>
    a odrl:Policy ;
    odrl:inheritFrom <http://odrlapi.appspot.com/samples/sample048> ;
    odrl:permission [
        odrl:assigner <http://example.com/asset:555> ;
        odrl:action odrl:print
    ] .

SHACL Shape:

odrl:InheritanceShape
    a sh:NodeShape ;
    sh:targetClass odrl:Policy ;
    sh:property [
        sh:path [ sh:oneOrMorePath [ sh:inversePath odrl:inheritFrom ]] ;
        sh:disjoint odrl:inheritFrom
    ] .

Other validations

A. OWL Validation

OPTIONAL: Validation that the policy document, together with the ontology, are consistent.

B. Strict validation of cardinalities

Whereas we read in the spec: "An ODRL Policy of subclass Offer must have one assigner property value" we cannot validate directly this: the assigner may have been given out of the policy, at the policy root level or inherited. Offers missing an assigner cannot be declared invalid unless the normalization step is done before. (same applies to cardinalities of Agreement and Set).