Generating reports using SPARQL
We use a triple-store (GraphDB Free Edition) to store the data graph and the test results for querying. We used three graphs to store - data, constraints, and test-results. We show simplified queries here without reference to specific graphs. We used a reasoner (HermiT) to identify inferences. GraphDB also provides some reasoning/inferencing capabilities in role as a triple-store.
The first query, listed in Listing 1., identifies messages from the tests as actionable items, shown in Table 1.
1 PREFIX sh: <http://www.w3.org/ns/shacl#>
2 SELECT DISTINCT ?msg ?test WHERE {
3 ?x a sh:ValidationResult .
4 ?x sh:resultMessage ?msg .
5 ?x sh:sourceConstraint ?test .
6 }
msg | test |
---|---|
Consent should state data storage periods | Q:ConsentHasStoragePeriod |
Consent should cover all purposes http://example.com/Quantcast#InformationStorageAccessWithPartners for same processing activities http://example.com/Quantcast#StoreIdentifiers | Q:ConsentAllPurposesForSameProcessing |
Consent should cover all purposes http://example.com/Quantcast#InformationStorageAccessWithPartners for same processing activities http://example.com/Quantcast#UseIdentifiers | Q:ConsentAllPurposesForSameProcessing |
Consent should have a timestamp | Q:ConsentHasTimestamp |
The second query, shown in Listing 2. lists the GDPR articles being tested and their status. It helps assess the coverage of GDPR and to see which items have failing tests, as shown in Table 2.
1 PREFIX sh: <http://www.w3.org/ns/shacl#>
2 PREFIX s: <http://example.com/Quantcast/shapes#>
3 SELECT DISTINCT ?gdpr ?result ?msg WHERE {
4 ?test s:linkToGDPR ?gdpr .
5 BIND(NOT EXISTS {
6 ?x sh:sourceConstraint ?test .
7 } as ?result )
8 OPTIONAL {
9 ?x sh:sourceConstraint ?test .
10 ?x sh:resultMessage ?msg .
11 }
12 } ORDER BY ?gdpr
gdpr | result | msg |
---|---|---|
gdpr:article13-1-e | true | |
gdpr:article13-2-a | false | Consent should state data storage periods |
gdpr:article14-1-e | true | |
gdpr:article14-2-a | false | Consent should state data storage periods |
gdpr:article30-1-d | true | |
gdpr:article4-11 | true | |
gdpr:article44 | true | |
gdpr:article5-1-e | false | Consent should state data storage periods |
gdpr:article7-2 | true | |
gdpr:article7-3 | true | |
gdpr:recital32 | true | |
gdpr:recital39 | false | Consent should state data storage periods |
gdpr:recital42 | true | |
gdpr:recital43 | true |
The third query, shown in Listing 3., generates a 'report', as in Table 3., showing the constraints (test), their type (automatic or manual), link to GDPR, result (pass or fail), the failing node, and message.
1 PREFIX c: <http://example.com/Quantcast/shapes#>
2 PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
3 PREFIX sh: <http://www.w3.org/ns/shacl#>
4 PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
5 SELECT DISTINCT ?name ?test ?gdpr ?result ?node ?msg
6 WHERE {
7 ?x a c:Constraint .
8 ?x sh:name ?name .
9 BIND(IF(EXISTS{
10 ?x a c:AutomaticallyCheckedConstraint},
11 "Automatic"^^xsd:string, "Manual"^^xsd:string)
12 as ?test)
13 OPTIONAL { ?x c:linkToGDPR ?gdpr }
14 BIND(IF(EXISTS{
15 ?y sh:sourceConstraint ?x},
16 "FAIL"^^xsd:string, "PASS"^^xsd:string)
17 as ?result)
18 OPTIONAL {
19 FILTER EXISTS { ?y sh:sourceConstraint ?x }
20 ?y sh:focusNode ?node .
21 ?y sh:resultMessage ?msg .
22 }
23 } ORDER BY ?name
name | test | gdpr | result | node | msg |
---|---|---|---|---|---|
Consent != Inactivity | Manual | gdpr:recital32 | PASS | ||
Consent != Pre-ticked Boxes | Manual | gdpr:recital32 | PASS | ||
Consent != Silence | Manual | gdpr:recital32 | PASS | ||
Consent --> Data Subject | Automatic | gdpr:article4-11 | PASS | ||
Consent --> Given To | Automatic | PASS | |||
Consent --> Location | Automatic | PASS | |||
Consent --> Medium | Automatic | gdpr:article7-2 | PASS | ||
Consent --> Medium | Automatic | gdpr:recital32 | PASS | ||
Consent --> Personal Data | Automatic | gdpr:article4-11 | PASS | ||
Consent --> Personal Data | Automatic | gdpr:recital32 | PASS | ||
Consent --> Processing | Automatic | gdpr:article4-11 | PASS | ||
Consent --> Processing | Automatic | gdpr:recital32 | PASS | ||
Consent --> Provided By | Automatic | gdpr:article7-2 | PASS | ||
Consent --> Purpose | Automatic | gdpr:recital32 | PASS | ||
Consent --> Purpose | Automatic | gdpr:recital42 | PASS | ||
Consent --> Status | Automatic | PASS | |||
Consent --> Timestamp | Automatic | FAIL | Q:Consent20190415120753 | Consent should have a timestamp | |
Consent --> Timestamp | Automatic | FAIL | Q:Consent20190415140000 | Consent should have a timestamp | |
Consent == Choice | Manual | PASS | |||
Consent == Freely Given | Manual | gdpr:article4-11 | PASS | ||
Consent == Specific | Manual | gdpr:article4-11 | PASS | ||
Consent == Statement of Clear Action | Manual | gdpr:article4-11 | PASS | ||
Consent == Unambigious | Manual | gdpr:article4-11 | PASS | ||
Consent Generating Activity | Automatic | PASS | |||
Consent Request == Clear | Manual | gdpr:recital32 | PASS | ||
Consent Request == Concise | Manual | gdpr:recital32 | PASS | ||
Consent Request == Not Disruptive | Manual | gdpr:recital32 | PASS | ||
Consent Template | Automatic | PASS | |||
Ease of Withdraw Consent | Manual | gdpr:article7-3 | PASS | ||
Many Processing x One Purpose | Automatic | gdpr:recital32 | PASS | ||
One Processing x Many Purposes | Automatic | gdpr:recital32 | FAIL | Q:Consent20190415120753 | Consent should cover all purposes Q:InformationStorageAccessWithPartners for same processing activities Q:StoreIdentifiers |
One Processing x Many Purposes | Automatic | gdpr:recital32 | FAIL | Q:Consent20190415140000 | Consent should cover all purposes Q:InformationStorageAccessWithPartners for same processing activities Q:StoreIdentifiers |
One Processing x Many Purposes | Automatic | gdpr:recital32 | FAIL | Q:Consent20190415120753 | Consent should cover all purposes Q:InformationStorageAccessWithPartners for same processing activities Q:UseIdentifiers |
One Processing x Many Purposes | Automatic | gdpr:recital32 | FAIL | Q:Consent20190415140000 | Consent should cover all purposes Q:InformationStorageAccessWithPartners for same processing activities Q:UseIdentifiers |
Personal Data --> Storage Period | Automatic | gdpr:article13-2-a | FAIL | Q:CATQInfoStorageAccess | Consent should state data storage periods |
Personal Data --> Storage Period | Automatic | gdpr:article13-2-a | FAIL | Q:CATTPInfoStorageAccess | Consent should state data storage periods |
Personal Data --> Storage Period | Automatic | gdpr:article13-2-a | FAIL | Q:Consent20190415120753 | Consent should state data storage periods |
Personal Data --> Storage Period | Automatic | gdpr:article13-2-a | FAIL | Q:Consent20190415140000 | Consent should state data storage periods |
Personal Data --> Storage Period | Automatic | gdpr:article14-2-a | FAIL | Q:CATQInfoStorageAccess | Consent should state data storage periods |
Personal Data --> Storage Period | Automatic | gdpr:article14-2-a | FAIL | Q:CATTPInfoStorageAccess | Consent should state data storage periods |
Personal Data --> Storage Period | Automatic | gdpr:article14-2-a | FAIL | Q:Consent20190415120753 | Consent should state data storage periods |
Personal Data --> Storage Period | Automatic | gdpr:article14-2-a | FAIL | Q:Consent20190415140000 | Consent should state data storage periods |
Personal Data --> Storage Period | Automatic | gdpr:article5-1-e | FAIL | Q:CATQInfoStorageAccess | Consent should state data storage periods |
Personal Data --> Storage Period | Automatic | gdpr:article5-1-e | FAIL | Q:CATTPInfoStorageAccess | Consent should state data storage periods |
Personal Data --> Storage Period | Automatic | gdpr:article5-1-e | FAIL | Q:Consent20190415120753 | Consent should state data storage periods |
Personal Data --> Storage Period | Automatic | gdpr:article5-1-e | FAIL | Q:Consent20190415140000 | Consent should state data storage periods |
Personal Data --> Storage Period | Automatic | gdpr:recital39 | FAIL | Q:CATQInfoStorageAccess | Consent should state data storage periods |
Personal Data --> Storage Period | Automatic | gdpr:recital39 | FAIL | Q:CATTPInfoStorageAccess | Consent should state data storage periods |
Personal Data --> Storage Period | Automatic | gdpr:recital39 | FAIL | Q:Consent20190415120753 | Consent should state data storage periods |
Personal Data --> Storage Period | Automatic | gdpr:recital39 | FAIL | Q:Consent20190415140000 | Consent should state data storage periods |
Right to Withdraw | Automatic | gdpr:article7-3 | PASS | ||
Separation of Processing | Manual | gdpr:recital43 | PASS | ||
Third Party Categories | Automatic | gdpr:article44 | PASS | ||
Third Party Identities | Automatic | gdpr:article13-1-e | PASS | ||
Third Party Identities | Automatic | gdpr:article14-1-e | PASS | ||
Third Party Identities | Automatic | gdpr:article30-1-d | PASS | ||
Third Party Identities | Automatic | gdpr:article44 | PASS | ||
Third Party Safeguards | Automatic | PASS | |||
Withdraw Consent Information | Manual | gdpr:article7-3 | PASS |