/**
  * returns a collection of objects
  *
  * @param string $class the class of objects to fetch
  * @param string $url (optional) the URL to retrieve
  * @param mixed $parent (optional) the parent service/object
  * @param array $parm (optional) array of key/value pairs to use as
  *		query strings
  * @return \OpenCloud\Collection
  */
 public function Collection($class, $url = NULL, $parent = NULL, $parm = array())
 {
     // set the element name
     $collection = $class::JsonCollectionName();
     $element = $class::JsonCollectionElement();
     //$jsonname = $class::JsonName();
     // save the parent
     if (!isset($parent)) {
         $parent = $this;
     }
     // determine the URL
     if (!$url) {
         $url = $parent->Url($class::ResourceName());
     }
     // add query string parameters
     if (count($parm)) {
         $url .= '?' . $this->MakeQueryString($parm);
     }
     // save debug info
     $this->debug('%s:Collection(%s, %s, %s)', get_class($this), $url, $class, $collection);
     // fetch the list
     $response = $this->Request($url);
     $this->debug('response %d [%s]', $response->HttpStatus(), $response->HttpBody());
     // check return code
     if ($response->HttpStatus() > 204) {
         throw new \OpenCloud\CollectionError(sprintf(_('Unable to retrieve [%s] list from [%s], ' . 'status [%d] response [%s]'), $class, $url, $response->HttpStatus(), $response->HttpBody()));
     }
     // handle empty response
     if (strlen($response->HttpBody()) == 0) {
         return new Collection($parent, $class, array());
     }
     // parse the return
     $obj = json_decode($response->HttpBody());
     if ($this->CheckJsonError()) {
         return FALSE;
     }
     // see if there is a "next" link
     if (isset($obj->links)) {
         if (is_array($obj->links)) {
             foreach ($obj->links as $link) {
                 if (isset($link->rel) && $link->rel == 'next') {
                     if (isset($link->href)) {
                         $next_page_url = $link->href;
                     } else {
                         throw new \OpenCloud\DomainError(_('unexpected [links] found with no [href]'));
                     }
                 }
             }
         }
     }
     // and say goodbye
     if (!$collection) {
         $coll_obj = new Collection($parent, $class, $obj);
     } elseif (isset($obj->{$collection})) {
         if (!$element) {
             $coll_obj = new Collection($parent, $class, $obj->{$collection});
         } else {
             // handle element levels
             $arr = array();
             foreach ($obj->{$collection} as $index => $item) {
                 $arr[] = $item->{$element};
             }
             $coll_obj = new Collection($parent, $class, $arr);
         }
     } else {
         $coll_obj = new Collection($parent, $class, array());
     }
     // if there's a $next_page_url, then we need to establish a
     // callback method
     if (isset($next_page_url)) {
         $coll_obj->SetNextPageCallback(array($this, 'Collection'), $next_page_url);
     }
     return $coll_obj;
 }