Internal and External Members

I've been spending some time thinking about how to implement external
members of a collection so that expected behaviors just naturally happen.

For me, the point of having external members is to allow multiple
collections to share the same resource.  It's to save each collection from
having to keep a physical copy of the same resource, and to insure that any
change in the resource will automatically be reflected in any collection
that has it as a member.

---------------

We're looking for an implementation of external members and internal
members that yield similar semantics for both.  Either they should both be
implemented as properties on the collection, or they should both be
implemented as URIs relative to the collection (as Dylan Barrell suggested
a few days ago).  Let's look at some scenarios for each implementation.

PROPFIND
PROPPATCH
COPY
LOCK

--------------

1. Treat both internal and external members as properties of the collection.

A Depth=0 COPY will copy a collection and the properties that list its
internal and external children.  The intuitive meaning of Depth=0 is that
only the collection, none of its children, should be copied.  So the spec
would have to make some special, explicit requirements about what happens
when you COPY Depth=0 a collection: the internalmembers and externalmembers
properties must be empty on the new collection.

A Depth=infinity COPY copies both the internalmembers and the
externalmembers property for the collection and for each internal member
that is a collection.  It copies the resources referenced by the
internalmembers property, but not those referenced by the externalmembers
property.

A Depth=0 LOCK should mean that you cannot add / remove members from the
collection.  Since a LOCK on an object also locks its properties, this
should have the expected effect.

A Depth=infinity LOCK locks the collection resource itself and all
resources referenced by the internalmembers property, recursively.

PROPFIND should list all members of a collection, both internal and
external, with the requested properties for each member.  PROPFIND would
examine both the internalmembers and the externalmembers properties, and
for each URI on either list, it would retrieve the requested properties.

PROPPATCH.  Presumably once you find the URI for either an internal or an
external member, you can do a PROPPATCH on that URI to set a property on
the member.  There is no way to set a property of a member-in-a-collection
(a property that applies to the resource only as a member of that
collection, e.g., who added it to the collection and when).

------------------

2. Treat both internal and external members as URIs relative to the
collection.  That is, when an external member is added to a collection, a
new resource is created relative to the collection.  (Its URI could be one
requested by the client or one determined by the server.)  This resource
has a membertype property = external and a location property = the URI
where its content is located, and no content.  (Or, as Dylan suggested, the
URI that points to the content location could itself be the content of the
member resource rather than a property on it.)  Note that this approach in
effect results in all members, even external members, having names (URIs)
in the collection, a point that has been contentious in the past.  It does
allow external members to carry a set of properties separate from the
properties on the resource they point to, a capability Mary Hofstede argued
for recently.

A Depth=0 COPY will copy a collection itself, but none of its members,
either internal or external.  This is the behavior that we expect for Depth=0.

A Depth=infinity COPY will copy all the resources that are members of the
collection, whether internal or external, recursively.  For the external
members, this does not involve following the URI to the content location.
It just means copying the resource that is the member of this collection.
If an external member points to a collection, nothing special happens.
It's still only the resource in this collection that gets copied.  (What is
the resourcetype of an external member that points to a collection?)

A Depth=0 LOCK should mean that you cannot add / remove members from the
collection.  However this is expected to be implemented today for internal
members, the same approach would be taken for external members.

A Depth=infinity LOCK locks the collection itself and all of its member
resources, recursively.  For external members, it locks only the URI
relative to the collection (so that none of its properties or content can
be changed), but does not lock the resource pointed to by its location
property (or by its content on Dylan's implementation).

PROPFIND should list all members of a collection, both internal and
external, with the requested properties for each member.  For external
members, do we display only properties on the URI relative to the
collection, or do we follow the URI in the location property and display
its properties?  I think the latter.  For a Depth>0 PROPFIND where an
external member points to a collection, we do expect to see the members of
that collection.  (What is the value of resourcetype for an external member
that points to a collection?)

PROPPATCH.  Presumably once you find the URI for either an internal or an
external member, you can do a PROPPATCH on that URI to set a property on
the member.  Now external members do have a URI within the collection as
well as a URI for the content location, so clients can set properties on
either URI.  The external member's URI within the collection can carry such
properties as who added it to the collection and when, while the URI it
points to can carry such properties as the resource's author, title,
content size, etc.

------------

I am inclined to think that we get desired behavior more naturally from
implementing each member, whether internal or external, as a resource in
the collection.  This works well for COPY, LOCK, and supports a separate
set of properties on an external-member-in-a-collection from the properties
that reside on the resource the external member points to.  PROPFIND needs
more thought, since it's no longer clear whether the client wants to see
the properties on the external-member-in-a-collection of the properties on
the resource the external member points to.

Note that DMA has chosen to implement both types of membership as
properties on a collection.  For those who are interested, here are some
excerpts from the DMA 1.0 specification.

--------------

DMA distinguishes between Direct and Referential containment:

"Direct containment. This models a 1:N, or one-to-many, relationship. A
containing object may contain multiple objects, but an object is directly
contained within at most one containing object. A containing object that
directly contains another object is the parent of that object. An object
that is directly contained within a parent object is a child of that
parent. Multiple directly contained objects are children. Direct
containment defines a strict hierarchy of objects with no cycles. Document
spaces implementing direct containment must prevent cycles. For example,
moving a parent into one of its children must be disallowed. DMA does not
limit the depth of the direct containment hierarchy, but a document space
may choose to impose a limit." 

"Referential containment. This models an N:M, or many-to-many,
relationship. Objects that are referentially contained within a containing
object are referred to as containees. A containing object that
referentially contains another object is referred to as a container of that
object. A container may contain multiple containees. A containee may be
contained within multiple containers. Cycles in referential containment
relationships are not disallowed by DMA, because they could be expensive to
prevent. A document space may choose to disallow them, however, in which
case it is obligated to enforce this. DMA defines operations that modify
containment hierarchies in such a fashion that cyclical referential
containment can be supported."

The point of having referential containment is to let multiple containers
share some of the same content.  This understanding of referential
containment also allows the same object to belong more than once to a
single container, and allows the same object to belong to the same
container once directly and one or more times by reference.

DMA also has the object infrastructure to allow properties to attach either
to the member itself or to the member/container relationship.

DMA implements both direct and referential containment using properties on
the container, one enumerating the container's childrem (direct members)
and the other enumerating the container's containees (members by reference).

--Judy



Name:		Judith A. Slein
E-Mail:		slein@wrc.xerox.com
Phone:  	(716) 422-5169
Fax:		(716) 422-2938

Xerox Corporation
Mail Stop 105-50C
800 Phillips Road
Webster, NY 14580

Received on Tuesday, 27 January 1998 13:16:47 UTC