<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE rdf:RDF [
    <!ENTITY rdf   "http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    <!ENTITY rdfs  "http://www.w3.org/2000/01/rdf-schema#">
    <!ENTITY owl   "http://www.w3.org/2002/07/owl#">
    <!ENTITY xsd   "http://www.w3.org/2001/XMLSchema#">
    <!ENTITY sswap "http://sswapmeet.sswap.info/sswap/">
]>

<rdf:RDF
    xmlns:rdf   = "&rdf;"
    xmlns:rdfs  = "&rdfs;"
    xmlns:owl   = "&owl;"
    xmlns:xsd   = "&xsd;"
    xmlns:sswap = "&sswap;"
    xmlns       = "&sswap;"
>

    <!-- Read in the SSWAP protocol to define all SSWAP terms -->
    <owl:Ontology rdf:about="&sswap;owlOntology">
        <owl:imports rdf:resource="&sswap;owlOntology"/>
    </owl:Ontology>

    <!-- Define this term using OWL + SSWAP semantics -->
    <owl:Class rdf:about="&sswap;Graph">

        <!-- Declare simple subsumption relations -->
        <rdfs:subClassOf rdf:resource="&sswap;SSWAP"/>

        <!-- Declare necessary conditions (i.e., subClassOf ) -->
        <!--
             These are essentially *optional* properties, so an
             individual may belong to this class and not have
             these properties instantiated.

             The cardinality constraints do not constrain how many
             instances of the property can exist, but it does allow
             a reasoner to infer how many semantically distinct
             objects (values) exist.  In the case of an
             owl:DatatypeProperty and an owl:maxCardinality = 1,
             it essentially means that if a value is defined, then
             it is the only allowed valued.  (Two semantically
             distinct values [e.g., 1 and 2] would yield the
             ontology inconsistent.
        -->
        <rdfs:subClassOf>
            <owl:Restriction>
                <owl:onProperty>
                    <owl:DatatypeProperty rdf:about="&sswap;metadata"/>
                </owl:onProperty>
                <owl:maxCardinality rdf:datatype="&xsd;nonNegativeInteger">1</owl:maxCardinality>
            </owl:Restriction>
        </rdfs:subClassOf>

        <!-- Declare necessary and sufficient conditions (i.e., equivalentClass) -->
        <!--
	The pattern below of using both <owl:allValuesFrom> and
	<owl:someValuesFrom> is a type of Qualified Cardinality Restriction
	(QCR).  The cardinality restriction is on this *class* definition,
	instead of (globally) on a property, as would be such if using
       	<owl:cardinality>, <owl:minCardinality>, or <owl:maxCardinality>.

	The <owl:allValuesFrom> lets a reasoner infer the class of the object
	of the restricted property.  In this case, the property
	sswap:hasMapping points from an individual of this class (sswap:Graph)
       	to an individual of rdf:type sswap:Subject.

	The <owl:someValuesFrom> lets a reasoner infer that if the property
	does indeed point to an individual of the named class, then there must
	be at least one such relation.  In this case, we're using the same
	property and class as used for <owl:allValuesFrom> as part the class
	definition, so the result is a cardinality constraint that an
	individual of sswap:Graph *must* have at least one sswap:hasMapping
       	property pointing to a sswap:Subject.

	This model identifies *required* properties, so an individual of this
       	class must have these properties.
        -->
  
        <owl:equivalentClass>
            <owl:Class>
                <owl:intersectionOf rdf:parseType="Collection">

                    <owl:Restriction>
                        <owl:onProperty>
                            <owl:ObjectProperty rdf:about="&sswap;hasMapping"/>
                        </owl:onProperty>
                        <owl:allValuesFrom>
                            <owl:Class rdf:about="&sswap;Subject"/>
                        </owl:allValuesFrom>
                    </owl:Restriction>

                    <owl:Restriction>
                        <owl:onProperty>
                            <owl:ObjectProperty rdf:about="&sswap;hasMapping"/>
                        </owl:onProperty>
                        <owl:someValuesFrom>
                            <owl:Class rdf:about="&sswap;Subject"/>
                        </owl:someValuesFrom>
                    </owl:Restriction>

                </owl:intersectionOf>
            </owl:Class>
        </owl:equivalentClass>

        <!-- Belonging to this class preclude belonging to these classes, and vice-versa -->
        <owl:disjointWith>
            <owl:Class rdf:about="&sswap;Provider"/>
        </owl:disjointWith>

        <owl:disjointWith>
            <owl:Class rdf:about="&sswap;Resource"/>
        </owl:disjointWith>

        <!-- Self-documenting comment about this term -->
        <rdfs:comment rdf:datatype="&xsd;string"
            >A required class. A sswap:Graph delineates a root or entry point for a suite of mappings.  For services, a "mapping" embeds the concept of taking some input and returning some output. An individual of this class is the object of the sswap:hasMapping relationship from sswap:Resource.  By differentially using sswap:operatesOn and sswap:hasMapping, one can, for example, differentiate between a pair of lists and a list of pairs.

Required predicates:
	hasMapping

Optional predicates:
	metadata</rdfs:comment>

    </owl:Class>

</rdf:RDF>
