mercoledì 31 ottobre 2007

RESTful Web Services Example 3.4 - Obtaining a list of buckets

Example 3.4 of the RESTful Web Services deals with obtaining a list of buckets (think of them as top-leve directories). This first version of the code will return a collection of strings, each one being the name of a single bucket. This is done by sending #getBuckets to an S3BucketList instance.

If you load the latest code (RWS-gc.25) from the RWS repository you’ll see many new changes. The ones we’re interested into are the S3Authorized class and the S3BucketList class.

The former is a class extracted via refactorings from the S3Object class, while the latter allows you to get the list of your buckets.

Take a look at S3BucketList>>getBuckets. The method is defined as:
| doc |
"Fetch all the buckets this user has defined.

Code taken from RESTful Web Services. Copyright © 2007 O'Reilly Media, Inc.
All rights reserved. Used with permission."

"GET the bucket list URI and build an XML DOM tree from it."
doc := XMLDOMParser
parseDocumentFrom: (self get: Host) contents readStream.
"For every bucket, collect its name"
^ doc // 'Bucket' / 'Name' collect: [:each | each contentString]

As you may see, the Smalltalk code is shorter than the corresponding Ruby code. That’s because we used Pastell, an XPath-like DSL for navigating XML DOM trees, instead of using a separate XPath library.

The first line of code creates a DOM tree from the XML document obtained by sending #get: to itself. #get: is one of the new messages added in the previous post.

In the second line, the DOM tree is sent a #// message. This message selects all the descendant nodes of an XML node whose name matches the argument of the message. In this example, the result of this message send will be a collection of nodes whose tag is 'Bucket'. This collection is a special subclass of OrderedCollection that can understand the Pastell messages, called PastellCollection

The list of nodes is sent another Pastell message, #/. This message selects all the child nodes whose tag matches the argument of the message. In this example, when sent to the PastellCollection instance returned by #//, it returns another PastellCollection whose elements have a 'Name' tag. We can retrieve the actual names of this elements by collect:ing their contentStrings.

In the next two examples, we’ll see how to model a single bucket as a Squeak object, and how to modify S3BucketList>>getBuckets in order to make it return a collection of objects instead of strings.

Nessun commento: