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

ORG Validation Suite

From Government Linked Data (GLD) Working Group Wiki
Jump to: navigation, search

This page describes a verification suite to assist implementers of ORG in checking that they are using the vocabulary appropriately. It is provided to support gathering implementation evidence as part of the W3C REC track process.

Verification approach

ORG provides a collection of terms intended to be useful for describing various aspects of organizations and organizational structure. Validating usage of such a vocabulary is difficult and cannot be completely automated.

  • There are few formal semantic constraints on the use vocabulary terms. The intended usage of terms is largely carried in the prose descriptions of them.
  • Implementers are free to use a subset of terms and to use additional terms (for cases where the coverage of ORG is insufficient).
  • There are no constraints on what it means to consume ORG data. The information may simply be published in machine readable form (e.g. as part of a government transparency initiative), may be used to drive visualizations of organizational structure or may be used in a more operational setting.

Our approach is to provide the specification for a minimal ORG consumer that extracts and describes different ORG resources from a data source. For example, given an organization then one affordance is to locate all sub organzations or organizational units. An implementation checker (a human) can thus walk through a sample ORG data source using the minimal consumer and confirm that the resources found match those expected from the source data. Verifying that the returned results are correct requires human interpretation.

We formalize this minimal ORG consumer as a set of SPARQL queries. To simplify testing the Working Group intends to offer an on line service which provides a simple HTML rendering of an ORG data source based on these queries.

A preliminary version of this service is available at: http://gld01.w3.org/

The display generated by this service on the test sample data below is visible at: http://gld01.w3.org/view?upload=upload-2013-05-22T15-39-45-0

Query set

Many of the verification queries are intended to extract part of the description of an organization. In the queries specified here the string $org should be replaced by <uri> where uri is the URI of the org:Organization instance being examined.

All SPARQL queries and update specifications below assume the following prefix declarations:

PREFIX rdf:        <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs:       <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl:        <http://www.w3.org/2002/07/owl#>
PREFIX skos:       <http://www.w3.org/2004/02/skos/core#>
PREFIX dct:        <http://purl.org/dc/terms/>
PREFIX vcard:      <http://www.w3.org/2006/vcard/ns#>
PREFIX org:        <http://www.w3.org/ns/org#>

Inference closure

Before applying any verification queries an inference closure should be formed as follows:

  • Create an RDF graph comprising the union of:
    • the data sample to be checked
    • the ORG ontology
    • any additional ontologies used in the implementation which declare mapping relationships between ORG and implementation-specific terms
  • Form an inference closure by applying the following SPARQL UPDATE on the graph:
PREFIX rdf:        <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs:       <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl:        <http://www.w3.org/2002/07/owl#>
PREFIX skos:       <http://www.w3.org/2004/02/skos/core#>
PREFIX org:        <http://www.w3.org/ns/org#>

INSERT {
    ?x ?p ?y .
} WHERE {
    ?sp rdfs:subPropertyOf+ ?p .
    ?x ?sp ?y .
};

INSERT {
    ?i a ?c .
} WHERE {
    ?p rdfs:domain ?c .
    ?i ?p ?x .
};

INSERT {
    ?i a ?c .
} WHERE {
    ?p rdfs:range ?c .
    ?x ?p ?i .
};

INSERT {
    ?i a ?c .
} WHERE {
    ?sc rdfs:subClassOf+ ?c .
    ?i a ?sc .
};

INSERT {
   ?x ?p ?y .
} WHERE {
   ?ip owl:inverseOf ?p .
   ?y ?ip ?x.
};

INSERT {
    ?agent   ?roleprop  ?org.
} WHERE {
  [] a org:Membership;
    org:member       ?agent;
    org:organization ?org;
    org:role         [ org:roleProperty ?roleprop ].
};

INSERT {
  ?agent  org:memberOf ?org.
} WHERE {
  ?agent org:holds  ?post.
  ?post  org:postIn ?org.
};

INSERT {
  [] a org:Membership;
    org:member       ?agent;
    org:organization ?org;
    org:role         ?role.
} WHERE {
  ?agent org:holds  ?post.
  ?post  org:postIn ?org.
  ?post  org:role   ?role.
};

INSERT {
    ?agent   org:memberOf  ?org.
} WHERE {
  [] a org:Membership;
    org:member       ?agent;
    org:organization ?org.
}

Any alternative inference closure process which computes (a super set of) those found by this SPARQL UPDATE may be used.

Core

List all organizations mentioned in the data.

SELECT * WHERE {
    ?org a org:Organization .
    OPTIONAL {?org skos:prefLabel ?prefLabel}
    OPTIONAL {?org rdfs:label ?label}
    OPTIONAL {?org dct:description ?description}
    OPTIONAL {?org org:identifier ?identifier}
    OPTIONAL {?org org:classification ?classification}
}

Structure

List all sub-organizations of a given organization.

SELECT * WHERE {
    ?subOrganization org:subOrganizationOf $org .
    OPTIONAL {
       ?subOrganization org:unitOf $org .
       BIND (true AS ?isUnitOf)
    }
}

Sites

List all sites of a given organization.

Note that the site information itself is OPTIONAL since the specification imposes no constraints on address representation and the recommended vocabulary (vcard) is currently subject to revision.

SELECT * WHERE {
    $org org:hasSite ?site .
    OPTIONAL {
       $org org:hasPrimarySite ?site .
       BIND (true AS ?isPrimarySite)
    }
    OPTIONAL {
       $org org:hasRegisteredSite ?site .
       BIND (true AS ?isRegisteredSite)
    }
    OPTIONAL {
        ?site org:siteAddress ?address .
        OPTIONAL { ?address vcard:fn  ?sitename }
        OPTIONAL { ?address vcard:tel / rdf:value ?telephone }
        OPTIONAL { ?address vcard:adr / vcard:street-address ?street }
        OPTIONAL { ?address vcard:adr / vcard:locality ?locality }
    }
}

Membership

List members of an organization.

SELECT * WHERE {
    ?member org:memberOf $org .
    OPTIONAL {
        ?member org:headOf $org .
        BIND (true as ?isHeadOf)
    }
    OPTIONAL { [] org:member ?member ; org:organization $org; org:role ?role  }
    OPTIONAL { ?member org:reportsTo ?reportsTo }
    OPTIONAL { ?member org:location ?location }
}

Posts

List posts in an organization, some post information is also tested by the membership query thanks to the closure rules.

SELECT * WHERE {
    ?post org:postIn $org .
    OPTIONAL { ?post org:reportsTo ?reportsTo }
    OPTIONAL { ?post org:heldBy ?postHolder }
    OPTIONAL { ?post org:role ?postRole }
}

Organization change

Lists event(s) which resulted in this organization and the associated precursor organizations.

SELECT * WHERE {
    $org org:resultedFrom ?event .
    OPTIONAL { ?event org:originalOrganization ?originalOrganization }
}

Collaboration

Lists consortia, projects or other collaborations which this organization is engaged in.

SELECT ?collaboration ?partner WHERE {
    $org org:memberOf ?collaboration .
    ?collaboration a org:OrganizationalCollaboration;
    OPTIONAL {
        ?partner org:memberOf ?collaboration .
        FILTER (?partner != $org)
    }
}

Example

This example demonstrates the result of the above verification queries when run on the following test data. Note that this sample is design to be an abstract, minimal test of the different features of ORG and not representative of real world organizations.

Example test data

@prefix rdf:        <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:       <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl:        <http://www.w3.org/2002/07/owl#> .
@prefix xsd:        <http://www.w3.org/2001/XMLSchema#> .
@prefix skos:       <http://www.w3.org/2004/02/skos/core#> .
@prefix foaf:       <http://xmlns.com/foaf/0.1/> .
@prefix dct:        <http://purl.org/dc/terms/> .
@prefix vcard:      <http://www.w3.org/2006/vcard/ns#> .
@prefix prov:       <http://www.w3.org/ns/prov#> .
@prefix vcard:      <http://www.w3.org/2006/vcard/ns#> .
@prefix org:        <http://www.w3.org/ns/org#> .

@prefix :        <http://example.com/sample1#> .

# Organizations

:org1 a org:FormalOrganization;
    skos:prefLabel "Org 1";
    org:hasUnit :unit1, :unit2 ;
    .

:unit1 a org:OrganizationalUnit;
    skos:prefLabel "Unit 1";
    org:hasRegisteredSite :site1;
    .

:unit2 a org:OrganizationalUnit;
    skos:prefLabel "Unit 2";
    .

# Sites

:site1 a org:Site ;
    rdfs:label "Site 1";
    org:siteAddress [
        a vcard:VCard;
        vcard:fn "Registered site for unit 1";
        vcard:tel [ rdf:value "1234" ];
        vcard:adr [ vcard:street-address "1 The Street"; vcard:locality "Our town"; vcard:postal-code "A1 42Z" ];
    ]
    .

# Posts

:assistantPost a org:Post;
    rdfs:label "Post of assistant to unit1's manager";
    org:postIn :unit1;
    org:role   :assistant;
    org:reportsTo :managerPost;
    .

:managerPost a org:Post;
     rdfs:label "Post of manager of unit1";
     org:postIn :unit1;
     org:role   :manager;
     .

# Roles
:manager a org:Role;
    rdfs:label "Manager";
    .

:assistant a org:Role;
    rdfs:label "Assistant";
    .

[] a org:Membership;
    org:member :p1;
    org:organization :unit1;
    org:role  :manager;
    .

# People

:boss1 a foaf:Person;
    foaf:name "The Boss";
    org:headOf :org1;
    .

:p2 a foaf:Person;
    foaf:name "Person 2";
    org:reportsTo :p1 ;
    org:holds     :assistantPost;
    .

:p1 a foaf:Person;
    foaf:name "Person 1";
    org:reportsTo :boss1 ;
    org:location "Mailstop 1/b";
    .

# Organizational history

:unit1a a org:OrganizationalUnit;
    skos:prefLabel "Unit 1a";
    .

:unit1b a org:OrganizationalUnit;
    skos:prefLabel "Unit 1b";
    .

:merger1 a org:ChangeEvent;
    rdfs:label "Unit merger";
    org:originalOrganization :unit1a, :unit1b;
    org:resultingOrganization :unit1 ;
    .

# Collaborations

:initiative a org:OrganizationalCollaboration;
    rdfs:label "Our cross-organizational initiative";
    org:hasMember :unit1, :unit2;
    .

Example result

*** List all organizations mentioned in the data

                 org = http://example.com/sample1#unit2 (Unit 2)
           prefLabel = Unit 2

                 org = http://example.com/sample1#org1 (Org 1)
           prefLabel = Org 1

                 org = http://example.com/sample1#initiative (Our cross-organizational initiative)
               label = Our cross-organizational initiative

                 org = http://example.com/sample1#unit1a (Unit 1a)
           prefLabel = Unit 1a

                 org = http://example.com/sample1#unit1b (Unit 1b)
           prefLabel = Unit 1b

                 org = http://example.com/sample1#unit1 (Unit 1)
           prefLabel = Unit 1

*** List all sub-organizations of a given organization

    Result for :org1
     subOrganization = http://example.com/sample1#unit1 (Unit 1)
            isUnitOf = true

     subOrganization = http://example.com/sample1#unit2 (Unit 2)
            isUnitOf = true

*** List all sites of a given organization

    Result for :unit1
                site = http://example.com/sample1#site1 (Site 1)
       isPrimarySite = true
    isRegisteredSite = true
             address = []
            sitename = Registered site for unit 1
           telephone = 1234
              street = 1 The Street
            locality = Our town

*** List members of an organization

    Result for :unit1
              member = http://example.com/sample1#p2 (Person 2)
                role = http://example.com/sample1#assistant (Assistant)
           reportsTo = http://example.com/sample1#p1 (Person 1)

              member = http://example.com/sample1#p1 (Person 1)
                role = http://example.com/sample1#manager (Manager)
           reportsTo = http://example.com/sample1#boss1 (The Boss)
            location = Mailstop 1/b

    Result for :initiative
              member = http://example.com/sample1#unit2 (Unit 2)

              member = http://example.com/sample1#unit1 (Unit 1)

    Result for :org1
              member = http://example.com/sample1#boss1 (The Boss)
            isHeadOf = true

*** List posts in an organization, some post information is also tested by the members query thanks to the closure rules.

    Result for :unit1
                post = http://example.com/sample1#managerPost (Post of manager of unit1)
            postRole = http://example.com/sample1#manager (Manager)

                post = http://example.com/sample1#assistantPost (Post of assistant to unit1's manager)
           reportsTo = http://example.com/sample1#managerPost (Post of manager of unit1)
          postHolder = http://example.com/sample1#p2 (Person 2)
            postRole = http://example.com/sample1#assistant (Assistant)

*** Lists event(s) which resulted in this organization and the associated precursor organizations

    Result for :unit1
               event = http://example.com/sample1#merger1 (Unit merger)
  originalOrganization = http://example.com/sample1#unit1a (Unit 1a)

               event = http://example.com/sample1#merger1 (Unit merger)
  originalOrganization = http://example.com/sample1#unit1b (Unit 1b)

*** Lists consortia, projects or other collaborations which this organization is engaged in

    Result for :unit2
       collaboration = http://example.com/sample1#initiative (Our cross-organizational initiative)
             partner = http://example.com/sample1#unit1 (Unit 1)

    Result for :unit1
       collaboration = http://example.com/sample1#initiative (Our cross-organizational initiative)
             partner = http://example.com/sample1#unit2 (Unit 2)