[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: Hierarchy - Part 2 - How we think our data would look in ATOM



We actually thought of something like this. In fact we experimented with a couple of approaches.

 

We thought of a bulk retrieval/update approach but it turned out that the performance implications were a nightmare. The structure you gave below would be pulling data from multiple tables. That’s fine in cases where someone is pulling in the whole address book but in most cases they aren’t. We needed finer granularity.

 

We although of an approach where we blew the information up and made it completely flat and then used links. This pretty much screams “RDF”. But trying to write code against disaggregated structures like this was a nightmare and if we didn’t dump everything into the feed then we would require users to make numerous GETs to walk the structure which was also too expensive.

 

In the end we figured a straight forward hierarchy with addressability was the way to go for this kind of deeply nested data.

 

                Yaron

 

From: John Panzer [mailto:jpanzer@xxxxxxx]
Sent: Thursday, June 21, 2007 2:56 PM
To: Yaron Goland
Cc: atom-protocol@xxxxxxx
Subject: Re: Hierarchy - Part 2 - How we think our data would look in ATOM

 

I agree with Tim et al that it seems that your chosen data model just may not map well onto AtomPub.  Certainly the mapping you're showing here, if it's the best one possible, just doesn't seem worthwhile.

If I were thinking about this from scratch, and looking at the implied data in the example LiveContacts document, I'd probably think of doing something like this as an Atom equivalent:

<feed xmlns="http://www.w3.org/2005/Atom" xmlns="Web3SBase:com.live.livecontacts" xmlns:Web3S="Web3S:">
  <fh:complete>
  <title>Contacts for demowld</title>
  <author><name>demowld@xxxxxxxxxxx</name></author>
  <updated>time of retrieval, or latest overall update date if available</updated>
  <entry>
    <title>My Friend</title>
    <updated>time of retrieval, or latest update date if available</updated>
    <id>tag:blah/69257004-966e-4ee1-8552-5564f17c7cad</id>
 
    <content type="application/windowsliveidcontact+xml">
       <Contact>
         <AutoUpdateEnabled>false</AutoUpdateEnabled>
         <Profiles>
            <Personal>
               <FirstName>My</FirstName>
               <LastName>Friend</LastName>
            </Personal>
         </Profiles>
         <Emails>
            <Email>
               <Web3S:ID>1</Web3S:ID>
               <EmailType>Personal</EmailType>
               <Address>myfriend@xxxxxxxxxxx</Address>
               <IsIMEnabled>false</IsIMEnabled>
               <IsDefault>true</IsDefault>
            </Email>
         </Emails>
         <Locations>
            <Location>
               <Web3S:ID>1</Web3S:ID>
               <LocationType>Personal</LocationType>
               <StreetLine>456 Minor Street</StreetLine>
               <PrimaryCity>Redmond</PrimaryCity>
               <Subdivision>WA</Subdivision>
               <PostalCode>98052</PostalCode>
               <CountryRegion>USA</CountryRegion>
               <IsDefault>false</IsDefault>
            </Location>
         </Locations>
      </Contact>
  </entry>
</feed>

So owner<-->author in Atom-ese, the feed title element just gives a human-readable quick summary of the data, IDs are mapped into global Atom IDs (I know, issues with global uniqueness still remain to be dealt with), and the rest of the attributes get their own MIME type and are embedded inside an entry's content.  No need for recursive hierarchy yet, in this little toy example.  It's available of course if we want to use it. 

I'd probably then start layering some additional semantics involving the element addressing and probably PATCH.  I think it's possible but I can't claim that it would work out without going into the details.  And it could well be that the end result isn't worth it for your specific case, or that the mappings above simply break for your second, third, and fourth use cases and you need something to handle them all; that is, you really do need something closer to RDF than Atom.

John



Yaron Goland wrote:

What I have tried to do in this e-mail is take an existing Web3S example data structure and translate it into ATOM. I tried my best to create something that was reasonable. I am sure there are better ways of handling this than what I have done, I just don't know what they are. So I'm coming to the group and asking for help. How can we both meet our addressability requirements and still be ATOM compliant?
 
Below is an example data structure for an address book encoded following Web3S. To be clear, I am not proposing Web3S to this group. I am just using this as an example to illustrate the data and capabilities we are trying to achieve.
 
<LiveContacts xmlns="Web3SBase:com.live.livecontacts" xmlns:Web3S="Web3S:">
   <Owner>
      <WindowsLiveID>demowld@xxxxxxxxxxx</WindowsLiveID>
   </Owner>
   <Contacts>
      <Contact>
         <Web3S:ID>69257004-966e-4ee1-8552-5564f17c7cad</Web3S:ID>
         <AutoUpdateEnabled>false</AutoUpdateEnabled>
         <Profiles>
            <Personal>
               <FirstName>My</FirstName>
               <LastName>Friend</LastName>
            </Personal>
         </Profiles>
         <Emails>
            <Email>
               <Web3S:ID>1</Web3S:ID>
               <EmailType>Personal</EmailType>
               <Address>myfriend@xxxxxxxxxxx</Address>
               <IsIMEnabled>false</IsIMEnabled>
               <IsDefault>true</IsDefault>
            </Email>
         </Emails>
         <Locations>
            <Location>
               <Web3S:ID>1</Web3S:ID>
               <LocationType>Personal</LocationType>
               <StreetLine>456 Minor Street</StreetLine>
               <PrimaryCity>Redmond</PrimaryCity>
               <Subdivision>WA</Subdivision>
               <PostalCode>98052</PostalCode>
               <CountryRegion>USA</CountryRegion>
               <IsDefault>false</IsDefault>
            </Location>
         </Locations>
      </Contact>
   </Contacts>
</LiveContacts>
 
One of the most important aspects of this structure is how to create URLs from it. A caller would need to know the structure's root out of band. Let's say that root is http://somewhere.live.com/somerootfeed/. In that case the root of this data structure would be URL addressable using http://somewhere.live.com/somerootfeed/com.live.livecontacts.LiveContacts. However anyone with a copy of this structure can reference any part of it at will. For example, if we wanted to address the PostalCode element inside of Location the URL would be http://somewhere.live.com/somerootfee
d/com.live.livecontacts.LiveContacts/com.live.livecontacts.Contacts/com.live.livecontacts.Contact(69257004-966e-4ee1-8552-5564f17c7cad)/com.live.livecontacts.Locations/com.live.livecontacts.Location(1)/com.live.livecontacts.PostalCode.
 
Yes, the URL is horrendous and we are discussing ways to compress it (see question 5.7 in http://dev.live.com/livedata/web3sFAQ.htm).
 
But the consequence of this design is that anyone can GET/PUT/POST/DELETE any element at any level in the data structure by knowing nothing other than the structure of the data. It's kind of a poor man's XPATH. It also allows us to meet the retrieval/update addressability requirements I explained in part 1 of this e-mail pair.
 
In representing this data structure in ATOM we wanted to keep the same addressability but if we really took this issue all the way to the extreme then every single element in the previous structured would have to be placed in its own entry. That just seemed to be taking things too far. So the rule I used in encoding the data into Atom is that any element that contains text will be treated as a foreign element of its parent. However any element that contains other elements would be modeled as a feed or an entry depending on context. I assume that we would have to come out with some kind of extension to ATOM that would make it possible to address foreign elements directly so we could keep the same level of addressability we currently have.
 
Another benefit of the previous data structure is that all the data is completely self describing. In the case of ATOM, feed/entry don't describe our actual syntax or semantics. To solve this problem we use category. We are required to use the term attribute but we really don't have a good use for it so we just leave it blank. Instead we use the scheme attribute to encode a URL that identifies the syntax and semantics of the associated entry or feed.
 
I have discussed how we handled author, title, updated, summary and id in a separate email so I won't repeat that information here.
 
I also need to ask Mark Nottingham if I used <fh:complete/> correctly. While complete can be put into a feed it isn't clear to me if it automatically applies to all of its children hierarchically. Also if someone retrieves a child separately wouldn't they need the fh:complete value to be there anyway? For now we put fh:complete into all of the feed elements.
 
I created a modified form of the ATOM RelaxNG schema so it should (famous last words) properly validate the content elements that contain atom feeds. I then ran that modified RelaxNG schema using JING against the example I give below. I realize that the schema can never be complete (e.g. one must read the spec) but I hope this at least will catch any gratuitous errors.
 
So, here is the result. Again, I'm not claiming this is the best, perfect or even right way to handle our data needs in atom. This is just the result of me trying to come up with something that seemed to keep with both the syntax and spirit of ATOM as well as meet most of our needs. Comments are actively solicited.
 
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="http://example.com/joe@xxxxxxxx/LiveContacts"
         xmlns:L="http://live.com/LiveContacts" xmlns:fh="http://purl.org/syndication/history/1.0">
   <title/><author><name>a</name></author><updated>0001-01-01T01:00:00</updated><fh:complete/>
   <id>http://somewhere.live.com/somerootfeed/LiveContacts</id>
   <link rel="edit" type="application/atom+xml" href="">
   <category term="" scheme="Web3SBase:com.live.livecontacts.livecontacts"/>
   <entry>
      <title/><updated>0001-01-01T01:00:00</updated>
      <id>http://somewhere.live.com/somerootfeed/LiveContacts/Owner</id>
      <link rel="edit" type="application/atom+xml" href="">
      <category term="" scheme="Web3SBase:com.live.livecontacts.owner"/>
      <L:WindowsLiveid>demowld@xxxxxxxxxxx</L:WindowsLiveid>
   </entry>
   <entry>
      <title/><updated>0001-01-01T01:00:00</updated>
      <id>http://somewhere.live.com/somerootfeed/LiveContacts/Contacts</id>
      <link rel="edit" type="application/atom+xml" href="">
      <category term="" scheme="Web3SBase:com.live.livecontacts.Contacts"/>
      <content type="application/atom+xml">
         <feed>
            <title/><author><name>a</name></author><updated>0001-01-01T01:00:00</updated><fh:complete/>
            <id>http://somewhere.live.com/somerootfeed/LiveContacts/Contacts?itemsContainer</id>
            <entry>
               <title/><updated>0001-01-01T01:00:00</updated>
               <id>http://somewhere.live.com/somerootfeed/LiveContacts/Contacts/Contact(69257004-966e-4ee1-8552-5564f17c7cad)</id>
               <link rel="edit" type="application/atom+xml" href="">
               <category term="" scheme="Web3SBase:com.live.livecontacts.Contact"/>
               <L:AutoUpdateEnabled>false</L:AutoUpdateEnabled>
               <content type="application/atom+xml">
                  <feed>
                     <title/><author><name>a</name></author><updated>0001-01-01T01:00:00</updated><fh:complete/>
                     <id>http://somewhere.live.com/somerootfeed/LiveContacts/Contacts/Contact(69257004-966e-4ee1-8552-5564f17c7cad)?itemsContainer</id>
                     <entry>
                        <title/><updated>0001-01-01T01:00:00</updated>
                        <id>http://somewhere.live.com/somerootfeed/LiveContacts/Contacts/Contact(69257004-966e-4ee1-8552-5564f17c7cad)/Profiles</id>
                        <link rel="edit" type="application/atom+xml" href="">
                        <category term="" scheme="Web3SBase:com.live.livecontacts.Profiles"/>
                        <content type="application/atom+xml">
                           <feed>
                              <title/><author><name>a</name></author><updated>0001-01-01T01:00:00</updated><fh:complete/>
                              <id>http://somewhere.live.com/somerootfeed/LiveContacts/Contacts/Contact(69257004-966e-4ee1-8552-5564f17c7cad)/Profiles?itemsContainer</id>
                              <entry>
                                 <title/><updated>0001-01-01T01:00:00</updated>
                                 <id>http://somewhere.live.com/somerootfeed/LiveContacts/Contacts/Contact(69257004-966e-4ee1-8552-5564f17c7cad)/Profiles/Personal</id>
                                 <link rel="edit" type="application/atom+xml" href="">
                                 <category term="" scheme="Web3SBase:com.live.livecontacts.Personal"/>
                                 <L:FirstName>My</L:FirstName>
                                 <L:LastName>Friend</L:LastName>
                              </entry>
                           </feed>
                        </content>
                     </entry>
                     <entry>
                        <title/><updated>0001-01-01T01:00:00</updated>
                        <id>http://somewhere.live.com/somerootfeed/LiveContacts/Contacts/Contact(69257004-966e-4ee1-8552-5564f17c7cad)/Emails</id>
                        <link rel="edit" type="application/atom+xml" href="">
                        <category term="" scheme="Web3SBase:com.live.livecontacts.Emails"/>
                        <content type="application/atom+xml">
                           <feed>
                              <title/><author><name>a</name></author><updated>0001-01-01T01:00:00</updated><fh:complete/>
                              <id>http://somewhere.live.com/somerootfeed/LiveContacts/Contacts/Contact(69257004-966e-4ee1-8552-5564f17c7cad)/Emails?itemsContainer</id>
                              <entry>
                                 <title/><updated>0001-01-01T01:00:00</updated>
                                 <id>http://somewhere.live.com/somerootfeed/LiveContacts/Contacts/Contact(69257004-966e-4ee1-8552-5564f17c7cad)/Emails/Email(1)</id>
                                 <link rel="edit" type="application/atom+xml" href="">
                                 <category term="" scheme="Web3SBase:com.live.livecontacts.Email"/>
                                 <L:EmailType>Personal</L:EmailType>
                                 <L:Address>myfriend@xxxxxxxxxxx</L:Address>
                                 <L:IsIMEnabled>false</L:IsIMEnabled>
                                 <L:IsDefault>true</L:IsDefault>
                              </entry>
                           </feed>
                        </content>
                     </entry>
                     <entry>
                        <title/><updated>0001-01-01T01:00:00</updated>
                        <id>http://somewhere.live.com/somerootfeed/LiveContacts/Contacts/Contact(69257004-966e-4ee1-8552-5564f17c7cad)/Locations</id>
                        <link rel="edit" type="application/atom+xml" href="">
                        <category term="" scheme="Web3SBase:com.live.livecontacts.Locations"/>
                        <content type="application/atom+xml">
                           <feed>
                              <title/><author><name>a</name></author><updated>0001-01-01T01:00:00</updated><fh:complete/>
                              <id>http://somewhere.live.com/somerootfeed/LiveContacts/Contacts/Contact(69257004-966e-4ee1-8552-5564f17c7cad)/Locations?itemsContainer</id>
                              <entry>
                                 <title/><updated>0001-01-01T01:00:00</updated>
                                 <id>http://somewhere.live.com/somerootfeed/LiveContacts/Contacts/Contact(69257004-966e-4ee1-8552-5564f17c7cad)/Locations/Location(1)</id>
                                 <link rel="edit" type="application/atom+xml" href="">
                                 <category term="" scheme="Web3SBase:com.live.livecontacts.Location"/>
                                 <L:LocationType>Personal</L:LocationType>
                                 <L:StreetLine>456 Minor Street</L:StreetLine>
                                 <L:PrimaryCity>Redmond</L:PrimaryCity>
                                 <L:Subdivision>WA</L:Subdivision>
                                 <L:PostalCode>98052</L:PostalCode>
                                 <L:CountryRegion>USA</L:CountryRegion>
                                 <L:IsDefault>false</L:IsDefault>
                              </entry>
                           </feed>
                        </content>
                     </entry>
                  </feed>
               </content>
            </entry>
         </feed>
      </content>
   </entry>
</feed>