Re: class hierarchy of containers

[I think you figured it out but I apologize, I have evidently messed up 
the end of my previous email by accidentally inserted a copy of another 
section, in the following:

So, maybe the actual hierarchy we need is this: 
<delete>Now, the question is whether this makes more sense than if we 
flipped the whole tree up-side-down. This requires thinking in terms of 
expanded capabilities instead of restrictions. We start from the simplest 
class and add to it as we go down. This gives us: </delete>

Container (aka BasicContainer) 
   | 
   ------- IndirectContainer (adds membershipResource, hasMemberRelation, 
isMemberOfRelation, and insertedContentRelation properties) 
                | 
                 ------- DirectContainer (restricts 
insertedContentRelation property to ldp:MemberSubjec


]

This being said, I expected you to barf at my proposal that " if a client 
only knows how/wants to deal with BasicContainers, with this model they 
would simply ignore the whole membership stuff and be fine just looking at 
the containment (container ldp:contains resource)" for exactly the reason 
you mention ("volunteering to the army").

Given that, I think we're better off going back to a simple, flat 
hierarchy with an abstract base class Container and three independent 
subclasses: BasicContainer, DirectContainer, and IndirectContainer.

Introducing any form of inheritance between these three containers seem to 
bring more undesirable effects than gain. Does anyone actually have a use 
case for having one of those classes derive from another?

Regards.
--
Arnaud  Le Hors - Software Standards Architect - IBM Software Group




From:   "henry.story@bblfish.net" <henry.story@bblfish.net>
To:     Arnaud Le Hors/Cupertino/IBM@IBMUS, 
Cc:     "Linked Data Platform (LDP) Working Group" <public-ldp-wg@w3.org>, 
Sandro Hawke <sandro@w3.org>
Date:   02/25/2014 03:30 AM
Subject:        Re: class hierarchy of containers




On 25 Feb 2014, at 06:25, Arnaud Le Hors <lehors@us.ibm.com> wrote:

Thanks Henry for taking a crack at this. 

However, this doesn't quite match what's in the current draft. The current 
draft actually has BasicContainer as a subclass of DirectContainer rather 
than Container. 

Container (aka IndirectContainer) 
   | 
   ------- DirectContainer (restricts insertedContentRelation property to 
ldp:MemberSubject) 
                | 
                 ------- BasicContainer (restricts membershipResource 
property to <> and hasMemberRelation property to ldp:contains) 

The whole idea behind this hierarchy being that we just add more 
constraints as we go down the hierarchy. 

yes. That's the point of trying to describe the BasicContainer in terms of 
owl:Restriction-s. 
Btw I discovered that owl2 has the restriction hasSelf ( see: 
http://www.w3.org/TR/owl2-quick-reference/ )
so that we can now I think correctly write the restrictions like this:

ldp:DirectContainer 
    owl:subClassOf ldp:Container,
                   [ a owl:Restriction;
                     owl:onProperty ldp:insertedContentRelation;
                     owl:hasValue ldp:MemberSubject
                   ] .

ldp:BasicContainer 
    owl:subClassOf ldp:DirectContainer,
                   [ a owl:Restriction;
                     owl:onProperty ldp:membershipResource;
                     owl:hasSelf "true"^^xsd:boolean ],
                   [ a owl:Restriction;
                     owl:onProperty ldp:hasMemberRelation;
                     owl:hasValue ldp:contains ] .

As I mentioned in my original e-mail this is a bit weird, because each 
LDPC can only have one ldp:membershipResource, 
ldp:hasMemberRelation, ldp:insertedContentRelation property ( they are all 
owl:FunctionalProperties as I added to the 
ontology below) and yet we are saying that  the superclass ldp:Container 
also has an ldp:contains relation and 
these other relations too. But if an ldp:BasicContainer should be thought 
of as an ldp:Container with the 
above restrictions meaning that ldp:contains is then a "membership 
property", then what are the ldp:contains relations
on the ldp:Container classes that are not ldp:BasicContainers? Why would 
these not also be membership properties? 

I think this may reveal another way of approaching the doubt that Sandro 
Hawke has with the current model
as he expressed in this e-mail 
http://lists.w3.org/Archives/Public/public-ldp-wg/2014Feb/0097.html


You're missing the isMemberOfRelation property (formerly known as 
membershipPredicateInverse). I think it would look something like that in 
your model: 

ldp:isMemberOfRelation a rdf:Property; 
   rdfs:domain  ldp:Container; 
   rdfs:range rdf:Property. 


yes. That makes the owl restrictions a bit more complex to write out. But 
it should not
make much difference as if you recall there was a simple proposal by 
Richard Cyganiak to 
have just one relation -  ldp:memberRelation  - which could do the job for 
inverse 
properties by using owl:inverseOf as in this example:

 <> a ldp:DirectContainer;
    ldp:memberRelation [ owl:inverseOf accounting:ows ];
    ldp:membershipResource <#me> .

( perhaps people now have less problem with owl, and would be willing to 
reconsider that decision )

With that notation my above restrictions remain simple, otherwise I'd need 
to use the owl:union 
construct I think.

Here is the version that takes your above comments into account, and adds 
labels for Kingsley.

~~~~~~~~~~~~~~~~~ ldp ontology as accepted by group before last week 
~~~~~~~~~~~~~~~~~~~~~~

@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .

ldp:Resource a rdfs:Class;
  rdfs:label "ldp Resource";
  rdfs:comment """
     A HTTP resource whose state is represented in any way that conforms 
to the simple 
     lifecycle patterns and conventions in section 5. Linked Data Platform 
Resources.
  """ .

ldp:Container a rdfs:Class;
  rdfs:label "ldp Container";
  owl:subClassOf ldp:Resource;
  rdfs:comment """
    An LDPR representing a collection of member resources and/or contained 
documents 
    (RDF Document [rdf11-concepts]  or information resources [WEBARCH]) 
that responds 
    to client requests for creation, modification, and/or enumeration 
    of its members and documents, and that conforms to the simple 
lifecycle patterns 
    and conventions in section6. Linked Data Platform Containers.
  """;
  skos:editorialNote """
    This used to be known as the ldp:IndirectContainer. A client 
successfully posting 
  to an ldp:Container will create a new resource that is linked to this 
ldp:container 
  via an ldp:contains relation, but may also create what are currently 
known as membership
  properties.
  """ .


ldp:DirectContainer a rdfs:Class;
   owl:subClassOf ldp:Container;
   rdfs:comment """
   A LDPC that has the flexibility of choosing what form its membership 
triples take, 
   and allows members to be any resources [WEBARCH], not only documents.
   """ .


ldp:BasicContainer a rdfs:Class;
  rdfs:label "BasicContainer";
  owl:subClassOf ldp:DirectContainer;
  rdfs:comment """
  A LDPC that uses a single pre-defined predicate to link to both its 
contained and 
  member documents (information resources)
  """ .

ldp:contains a rdf:Property;
  rdfs:label "contains";
  rdfs:domain ldp:Container;
  rdfs:range ldp:Resource;
  rdfs:comment """
    the ldp:contains relation relates an ldp:Container to an information r
  """ .

ldp:membershipResource a rdf:Property, owl:FunctionalProperty;
  rdfs:label "membershipResource";
  rdfs:domain ldp:Container;
  rdfs:range  rdf:Resource .

ldp:hasMemberRelation a rdf:Property, owl:FunctionalProperty;
  rdfs:label "hasMemberRelation";
  rdfs:domain ldp:Container;
  rdfs:range  rdf:Property .

ldp:isMemberOfRelation a rdf:Property, owl:FunctionalProperty; 
   rdfs:label "isMemerOfRelation"
   rdfs:domain  ldp:Container; 
   rdfs:range rdf:Property.

ldp:insertedContentRelation a rdf:Property, owl:FunctionalProperty;
  rdfs:label "insertedContentRelation";
  rdfs:domain ldp:Container;
  rdfs:range  rdf:Resource .
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

(Of course I just cut and pasted the text from the spec, and a better 
ontology would
have to adapt these.)


Now, the question is whether this makes more sense than if we flipped the 
whole tree up-side-down.
This requires thinking in terms of expanded capabilities instead of 
restrictions. We start from the
simplest class and add to it as we go down. This gives us: 

Container (aka BasicContainer) 
   | 
   ------- DirectContainer (adds membershipResource, hasMemberRelation, 
isMemberOfRelation properties) 
                | 
                 ------- IndirectContainer (adds insertedContentRelation 
property) 




I think you could express it this way in OWL (I'm really no OWL expect so 
I apologize if there are mistakes in there):

~~~~~~~~~~~~~~~~~definition of the well known classes and relation 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix ldp: <http://www.w3.org/ns/ldp#> .

ldp:Resource a rdfs:Class;
  rdfs:comment """
     A HTTP resource whose state is represented in any way that conforms 
to the simple 
     lifecycle patterns and conventions in section 5. Linked Data Platform 
Resources.
  """ .

ldp:Container a rdfs:Class;
  owl:subClassOf ldp:Resource;
  rdfs:comment """
  An LDPR representing a collection of contained documents 
    (RDF Document [rdf11-concepts] or information resources [WEBARCH]) 
that responds 
    to client requests for creation, modification, and/or enumeration 
    of its documents, and that conforms to the simple lifecycle patterns 
    and conventions in section6. Linked Data Platform Containers.
  """;
  skos:editorialNote """
    This used to be known as the ldp:BasicContainer. A client successfully 
posting 
    to an ldp:Container will create a new resource that is linked to this 
container
    via an ldp:contains relation.
  """ .

ldp:contains a rdf:Property;
  rdfs:domain ldp:Container;
  rdfs:range ldp:Resource;
  rdfs:comment """
    the ldp:contains relation relates an ldp:Container to an information 
resource.
  """ .


ldp:DirectContainer a rdfs:Class;
   owl:subClassOf ldp:Container;
   rdfs:comment """
   A Container that also manages a configurable list of members. A client 
successfully posting 
   to an ldp:DirectContainer will create a new resource that is linked to 
this container
   via an ldp:contains relation and will also add a membership triple of 
either form: 
      membershipResource hasMemberRelation member 
    or 
      member isMemberOfRelation membershipResource. 
    in which the member is the created resource.
 """ .

ldp:membershipResource a rdf:Property;
  rdfs:domain ldp:DirectContainer;
  rdfs:range  rdf:Resource .

ldp:hasMemberRelation a rdf:Property;
  rdfs:domain ldp:DirectContainer;
  rdfs:range  rdf:Property .

ldp:isMemberOfRelation a rdf:Property;
  rdfs:domain ldp:DirectContainer;
  rdfs:range  rdf:Property .


ldp:IndirectContainer a rdfs:Class;
  owl:subClassOf ldp:DirectContainer;
  rdfs:comment """
    A DirectContainer providing the additional flexibility to have non 
information resources 
     [WEBARCH]) as members. A client successfully posting to an 
ldp:IndirectContainer will create 
     a new resource that is linked to this container via an ldp:contains 
relation and will also add 
     a membership triple of either form:
     membershipResource hasMemberRelation member 
    or 
      member isMemberOfRelation membershipResource. 
    in which the member is the object of the insertedContentRelation in 
the created resource.
  """.

ldp:insertedContentRelation a rdf:Property;
  rdfs:domain ldp:Container;
  rdfs:range  rdf:Property .

As I said on the call I've managed to convince myself that both ways make 
sense. 

I think what's key is that if a client only knows how/wants to deal with 
BasicContainers, with this model they would simply ignore the whole 
membership stuff and be fine just looking at the containment (container 
ldp:contains resource). 

What we loose here is the notion we had with the ldp:BasicContainer, 
namely that a client that 
POSTs to an  ldp:BasicContainer would know that  it does not have to worry 
about the membership 
triples it might create. We loose this because in the above ontology if 
something is an 
ldp:Container, it could also be an  ldp:IndirectContainer  or an 
ldp:DirectContainer. This 
follows from the two statements:

 { 
   ldp:IndirectContainer owl:subClassOf ldp:DirectContainer .
   ldp:DirectContainer owl:subClassOf ldp:Container .
 }

But following my arguments from the "volunteering to the army" counter use 
case - this means that a 
client does not know  if by POSTing a simple foaf Profile it may not be 
volunteering its user to the 
army too.  That is why a client can NOT "simply ignore the whole 
membership stuff".  After all the whole point
of these "membership predicates" is that they tell the client what other 
things are going to be done
if some content is POSTed to the LDPC. A client knowing this and POSTing 
is bound to know about those 
consequenecs, and so is bound to them. A client is not bound to 
consequences that are not mentioned 
explicitly - say if someone wires a LDPC so that it bombs a bank on 
POSTing there.

Without paging it would be just a case of the client searching the graph 
for the membership properties.
With paging though, things get more complicated as a client would need to 
page through all the pages
to find out if those relations existed.

I think that all that will happen is that if we accept this ontology, 
we'll end up wanting to define
a ldp:BasicContainer as follows

ldp:BasicContainer 
    owl:equivalentClass [ 
           owl:intersection ( ldp:Container 
                              [ owl:complementOf [ owl:unionOf ( 
ldp:IndirectContainer ldp:DirectContainer ) ] 
                            ) 
                         ] .

This seems different from the ontology I suggested above in that here the 
ldp:BasicContainer 
is non overlapping any members of the ldp:IndirectContainer or the 
ldp:DirectContainer. 
In the ontology I suggested above ldp:DirectContainer was a subclass of 
ldp:DirectContainer - though
we did note that there was something a bit awkward about that too, as it 
made ldp:contains be a membership
triple only in the case where ldp:contains was a attached to a 
ldp:BasicContainer !

I'm not as sure that a client that only knows how/wants to deal with 
DirectContainers can deal with IndirectContainers as if they were 
DirectContainers. For one thing I would expect them to get confused about 
not finding the contained resources in the list of members. 

So, maybe the actual hierarchy we need is this: 
Now, the question is whether this makes more sense than if we flipped the 
whole tree up-side-down. This requires thinking in terms of expanded 
capabilities instead of restrictions. We start from the simplest class and 
add to it as we go down. This gives us: 

Container (aka BasicContainer) 
   | 
   ------- IndirectContainer (adds membershipResource, hasMemberRelation, 
isMemberOfRelation, and insertedContentRelation properties) 
                | 
                 ------- DirectContainer (restricts 
insertedContentRelation property to ldp:MemberSubject) 


I think this way round makes more sense

 { 
   ldp:IndirectContainer owl:subClassOf ldp:Container .
   ldp:DirectContainer owl:subClassOf ldp:IndirectContainer .
 }

as it fits nicely the following owl rule

ldp:DirectContainer 
    owl:equivalentClass [ 
        owl:intersection  (
             ldp:IndirectContainer,
             [ a owl:Restriction;
               owl:onProperty ldp:insertedContentRelation;
               owl:hasValue ldp:MemberSubject
             ] 
         )
    ] .

But here we have this odd ldp:MemberSubject that is very ad-hoc, and that 
feels
like it was created just to make the class hierarchy work as shown. Things 
look less
ad-hoc if instead of ldp:MemberSubject we use owl:sameAs. Since owl:sameAs 
relates every
thing to itself then this should give the correct results.


I'd love for someone more fluent in this type of stuff to tell me which 
way is right. 

I hope the above helps.

What does this lead us to? 

1) The "volunteering for the army" counter use case brings to light that 
whatever we do we need a 
   ldp:BasicContainer for which the following has to be true:

ldp:BasicContainer owl:disjointWith [ owl:unionOf ( ldp:IndirectContainer 
ldp:DirectContainer ) ] .

2) we also want ldp:contains have as domain any of those containers

   ldp:contains rdfs:domain ldp:Container .

3) what distinguihes the IndirectContainer and the DirectContainer are 
just the types of "membership triples"
   that posting to such a container will create. 




Best regards.
--
Arnaud  Le Hors - Software Standards Architect - IBM Software Group


Social Web Architect
http://bblfish.net/

Received on Tuesday, 25 February 2014 17:51:07 UTC