Index: library/Zend/Gdata/Gapps.php
===================================================================
--- library/Zend/Gdata/Gapps.php	(revision 22018)
+++ library/Zend/Gdata/Gapps.php	(working copy)
@@ -37,6 +37,21 @@
 require_once 'Zend/Gdata/Gapps/NicknameFeed.php';
 
 /**
+ * @see Zend_Gdata_Gapps_GroupFeed
+ */
+require_once 'Zend/Gdata/Gapps/GroupFeed.php';
+
+/**
+ * @see Zend_Gdata_Gapps_MemberFeed
+ */
+require_once 'Zend/Gdata/Gapps/MemberFeed.php';
+
+/**
+ * @see Zend_Gdata_Gapps_OwnerFeed
+ */
+require_once 'Zend/Gdata/Gapps/OwnerFeed.php';
+
+/**
  * @see Zend_Gdata_Gapps_EmailListFeed
  */
 require_once 'Zend/Gdata/Gapps/EmailListFeed.php';
@@ -81,6 +96,11 @@
     const APPS_NICKNAME_PATH = '/nickname/2.0';
 
     /**
+     * Path to group feeds on the Google Apps server.
+     */
+    const APPS_GROUP_PATH = '/group/2.0';
+
+    /**
      * Path to email list feeds on the Google Apps server.
      */
     const APPS_EMAIL_LIST_PATH = '/emailList/2.0';
@@ -372,6 +392,80 @@
     }
 
     /**
+     * Retreive GroupFeed object containing multiple GroupEntry
+     * objects.
+     *
+     * @param mixed $location (optional) The location for the feed, as a URL
+     *          or Query.
+     * @return Zend_Gdata_Gapps_GroupFeed
+     * @throws Zend_Gdata_App_Exception
+     * @throws Zend_Gdata_App_HttpException
+     * @throws Zend_Gdata_Gapps_ServiceException
+     */
+    public function getGroupFeed($location = null)
+    {
+        if ($location === null) {
+            $uri  = self::APPS_BASE_FEED_URI . self::APPS_GROUP_PATH . '/';
+            $uri .= $this->getDomain();
+        } else if ($location instanceof Zend_Gdata_Query) {
+            $uri = $location->getQueryUrl();
+        } else {
+            $uri = $location;
+        }
+        return parent::getFeed($uri, 'Zend_Gdata_Gapps_GroupFeed');
+    }
+
+    /**
+     * Retreive MemberFeed object containing multiple MemberEntry
+     * objects.
+     *
+     * @param mixed $location (optional) The location for the feed, as a URL
+     *          or Query.
+     * @return Zend_Gdata_Gapps_MemberFeed
+     * @throws Zend_Gdata_App_Exception
+     * @throws Zend_Gdata_App_HttpException
+     * @throws Zend_Gdata_Gapps_ServiceException
+     */
+    public function getMemberFeed($location = null)
+    {
+        if ($location === null) {
+            require_once 'Zend/Gdata/App/InvalidArgumentException.php';
+            throw new Zend_Gdata_App_InvalidArgumentException(
+                    'Location must not be null');
+        } else if ($location instanceof Zend_Gdata_Query) {
+            $uri = $location->getQueryUrl();
+        } else {
+            $uri = $location;
+        }
+        return parent::getFeed($uri, 'Zend_Gdata_Gapps_MemberFeed');
+    }
+
+    /**
+     * Retreive OwnerFeed object containing multiple OwnerEntry
+     * objects.
+     *
+     * @param mixed $location (optional) The location for the feed, as a URL
+     *          or Query.
+     * @return Zend_Gdata_Gapps_OwnerFeed
+     * @throws Zend_Gdata_App_Exception
+     * @throws Zend_Gdata_App_HttpException
+     * @throws Zend_Gdata_Gapps_ServiceException
+     */
+    public function getOwnerFeed($location = null)
+    {
+        if ($location === null) {
+            require_once 'Zend/Gdata/App/InvalidArgumentException.php';
+            throw new Zend_Gdata_App_InvalidArgumentException(
+                    'Location must not be null');
+        } else if ($location instanceof Zend_Gdata_Query) {
+            $uri = $location->getQueryUrl();
+        } else {
+            $uri = $location;
+        }
+        return parent::getFeed($uri, 'Zend_Gdata_Gapps_OwnerFeed');
+    }
+
+    /**
      * Retreive EmailListFeed object containing multiple EmailListEntry
      * objects.
      *
@@ -465,6 +559,75 @@
     }
 
     /**
+     * Retreive a single GroupEntry object.
+     *
+     * @param mixed $location The location for the feed, as a URL or Query.
+     * @return Zend_Gdata_Gapps_GroupEntry
+     * @throws Zend_Gdata_App_Exception
+     * @throws Zend_Gdata_App_HttpException
+     * @throws Zend_Gdata_Gapps_ServiceException
+     */
+    public function getGroupEntry($location = null)
+    {
+        if ($location === null) {
+            require_once 'Zend/Gdata/App/InvalidArgumentException.php';
+            throw new Zend_Gdata_App_InvalidArgumentException(
+                    'Location must not be null');
+        } else if ($location instanceof Zend_Gdata_Query) {
+            $uri = $location->getQueryUrl();
+        } else {
+            $uri = $location;
+        }
+        return parent::getEntry($uri, 'Zend_Gdata_Gapps_GroupEntry');
+    }
+
+    /**
+     * Retreive a single MemberEntry object.
+     *
+     * @param mixed $location The location for the feed, as a URL or Query.
+     * @return Zend_Gdata_Gapps_MemberEntry
+     * @throws Zend_Gdata_App_Exception
+     * @throws Zend_Gdata_App_HttpException
+     * @throws Zend_Gdata_Gapps_ServiceException
+     */
+    public function getMemberEntry($location = null)
+    {
+        if ($location === null) {
+            require_once 'Zend/Gdata/App/InvalidArgumentException.php';
+            throw new Zend_Gdata_App_InvalidArgumentException(
+                    'Location must not be null');
+        } else if ($location instanceof Zend_Gdata_Query) {
+            $uri = $location->getQueryUrl();
+        } else {
+            $uri = $location;
+        }
+        return parent::getEntry($uri, 'Zend_Gdata_Gapps_MemberEntry');
+    }
+
+    /**
+     * Retreive a single OwnerEntry object.
+     *
+     * @param mixed $location The location for the feed, as a URL or Query.
+     * @return Zend_Gdata_Gapps_OwnerEntry
+     * @throws Zend_Gdata_App_Exception
+     * @throws Zend_Gdata_App_HttpException
+     * @throws Zend_Gdata_Gapps_ServiceException
+     */
+    public function getOwnerEntry($location = null)
+    {
+        if ($location === null) {
+            require_once 'Zend/Gdata/App/InvalidArgumentException.php';
+            throw new Zend_Gdata_App_InvalidArgumentException(
+                    'Location must not be null');
+        } else if ($location instanceof Zend_Gdata_Query) {
+            $uri = $location->getQueryUrl();
+        } else {
+            $uri = $location;
+        }
+        return parent::getEntry($uri, 'Zend_Gdata_Gapps_OwnerEntry');
+    }
+
+    /**
      * Retreive a single EmailListEntry object.
      *
      * @param mixed $location The location for the feed, as a URL or Query.
@@ -556,6 +719,77 @@
     }
 
     /**
+     * Create a new group from a GroupEntry.
+     *
+     * @param Zend_Gdata_Gapps_GroupEntry $group The group entry to insert.
+     * @param string $uri (optional) The URI where the group should be
+     *          uploaded to. If null, the default user creation URI for
+     *          this domain will be used.
+     * @return Zend_Gdata_Gapps_GroupEntry The inserted group entry as
+     *          returned by the server.
+     * @throws Zend_Gdata_App_Exception
+     * @throws Zend_Gdata_App_HttpException
+     * @throws Zend_Gdata_Gapps_ServiceException
+     */
+    public function insertGroup($group, $uri = null)
+    {
+        if ($uri === null) {
+            $uri  = self::APPS_BASE_FEED_URI . self::APPS_GROUP_PATH . '/';
+            $uri .= $this->getDomain();
+        }
+        $newEntry = $this->insertEntry($group, $uri, 'Zend_Gdata_Gapps_GroupEntry');
+        return $newEntry;
+    }
+
+    /**
+     * Create a new member from a MemberEntry.
+     *
+     * @param Zend_Gdata_Gapps_MemberEntry $member The member entry to insert.
+     * @param string $uri (optional) The URI where the group should be
+     *          uploaded to. If null, the default user creation URI for
+     *          this domain will be used.
+     * @return Zend_Gdata_Gapps_MemberEntry The inserted member entry as
+     *          returned by the server.
+     * @throws Zend_Gdata_App_Exception
+     * @throws Zend_Gdata_App_HttpException
+     * @throws Zend_Gdata_Gapps_ServiceException
+     */
+    public function insertMember($member, $uri = null)
+    {
+        if ($uri === null) {
+            require_once 'Zend/Gdata/App/InvalidArgumentException.php';
+            throw new Zend_Gdata_App_InvalidArgumentException(
+                    'URI must not be null');
+        }
+        $newEntry = $this->insertEntry($member, $uri, 'Zend_Gdata_Gapps_MemberEntry');
+        return $newEntry;
+    }
+
+    /**
+     * Create a new group from a OwnerEntry.
+     *
+     * @param Zend_Gdata_Gapps_OwnerEntry $owner The owner entry to insert.
+     * @param string $uri (optional) The URI where the owner should be
+     *          uploaded to. If null, the default user creation URI for
+     *          this domain will be used.
+     * @return Zend_Gdata_Gapps_OwnerEntry The inserted owner entry as
+     *          returned by the server.
+     * @throws Zend_Gdata_App_Exception
+     * @throws Zend_Gdata_App_HttpException
+     * @throws Zend_Gdata_Gapps_ServiceException
+     */
+    public function insertOwner($owner, $uri = null)
+    {
+        if ($uri === null) {
+            require_once 'Zend/Gdata/App/InvalidArgumentException.php';
+            throw new Zend_Gdata_App_InvalidArgumentException(
+                    'URI must not be null');
+        }
+        $newEntry = $this->insertEntry($owner, $uri, 'Zend_Gdata_Gapps_OwnerEntry');
+        return $newEntry;
+    }
+
+    /**
      * Create a new email list from an EmailListEntry.
      *
      * @param Zend_Gdata_Gapps_EmailListEntry $emailList The email list entry
@@ -932,6 +1166,358 @@
     }
 
     /**
+     * Create a new group.
+     *
+     * @param string $groupId A unique identifier for the group
+     * @param string $groupName The name of the group
+     * @param string $description A description of the group
+     * @param string $emailPermission The subscription permission of the group
+     * @return Zend_Gdata_Gapps_GroupEntry The group entry as created on the server.
+     */
+    public function createGroup($groupId, $groupName, $description = null, $emailPermission = null)
+    {
+        $i = 0;
+        $group = $this->newGroupEntry();
+        
+        $properties[$i] = $this->newProperty();
+        $properties[$i]->name = 'groupId';
+        $properties[$i]->value = $groupId;
+        $i++;
+        $properties[$i] = $this->newProperty();
+        $properties[$i]->name = 'groupName';
+        $properties[$i]->value = $groupName;
+        $i++;
+
+        if($description != null) {
+            $properties[$i] = $this->newProperty();
+            $properties[$i]->name = 'description';
+            $properties[$i]->value = $description;
+            $i++;
+        }
+
+        if($emailPermission != null) {
+            $properties[$i] = $this->newProperty();
+            $properties[$i]->name = 'emailPermission';
+            $properties[$i]->value = $emailPermission;
+            $i++;
+        }        
+        
+        $group->property = $properties;
+
+        return $this->insertGroup($group);
+    }
+
+    /**
+     * Retrieves a group based on group id
+     *
+     * @param string $groupId The unique identifier for the group
+     * @return Zend_Gdata_Gapps_GroupEntry The group entry as returned by the server.
+     */
+    public function retrieveGroup($groupId)
+    {
+        $query = $this->newGroupQuery($groupId);
+        //$query->setGroupId($groupId);
+
+        try {
+            $group = $this->getGroupEntry($query);
+        } catch (Zend_Gdata_Gapps_ServiceException $e) {
+            // Set the group to null if not found
+            if ($e->hasError(Zend_Gdata_Gapps_Error::ENTITY_DOES_NOT_EXIST)) {
+                $group = null;
+            } else {
+                throw $e;
+            }
+        }
+        return $group;
+    }
+
+    /**
+     * Retrieve all groups in the current domain. Be aware that
+     * calling this function on a domain with many groups will take a
+     * signifigant amount of time to complete. On larger domains this may
+     * may cause execution to timeout without proper precautions in place.
+     *
+     * @return Zend_Gdata_Gapps_GroupFeed Collection of Zend_Gdata_GroupEntry objects
+     *              representing all groups apart of the domain.
+     */
+    public function retrieveAllGroups() 
+    {
+        return $this->retrieveAllEntriesForFeed($this->retrievePageOfGroups());
+    }
+
+    /**
+     * Delete a group
+     *
+     * @param string $groupId The unique identifier for the group
+     */
+    public function deleteGroup($groupId)
+    {
+        $uri  = self::APPS_BASE_FEED_URI . self::APPS_GROUP_PATH . '/';
+        $uri .= $this->getDomain() . '/' . $groupId;
+
+        $this->delete($uri);
+    }
+    
+    /**
+     * Check to see if a member id or group id is a member of group
+     *
+     * @param string $memberId Member id or group group id
+     * @param string $groupId Group to be checked for
+     * @return bool True, if given entity is a member
+     */
+    public function isMember($memberId, $groupId)
+    {
+        $uri  = self::APPS_BASE_FEED_URI . self::APPS_GROUP_PATH . '/';
+        $uri .= $this->getDomain() . '/' . $groupId . '/member/' . $memberId;
+        
+        //if the enitiy is not a member, an exception is thrown
+        try {
+            $results = $this->get($uri);
+        } catch (Exception $e) {
+            $results = false;
+        }
+
+        if($results) {
+            return TRUE;
+        } else {
+            return FALSE;
+        }
+    }
+
+    /**
+     * Add an email address to a group as a member
+     *
+     * @param string $recipientAddress Email address, member id, or group id
+     * @param string $groupId The unique id of the group
+     * @return Zend_Gdata_Gapps_MemberEntry The member entry returned by the server
+     */
+    public function addMemberToGroup($recipientAddress, $groupId)
+    {
+        $member = $this->newMemberEntry();
+
+        $properties[] = $this->newProperty();
+        $properties[0]->name = 'memberId';
+        $properties[0]->value = $recipientAddress;
+
+        $member->property = $properties;
+
+        $uri  = self::APPS_BASE_FEED_URI . self::APPS_GROUP_PATH . '/';
+        $uri .= $this->getDomain() . '/' . $groupId . '/member';
+
+        return $this->insertMember($member, $uri);
+    }
+
+    /**
+     * Remove a member id from a group
+     *
+     * @param string $memberId Member id or group id
+     * @param string $groupId The unique id of the group
+     */
+    public function removeMemberFromGroup($memberId, $groupId)
+    {
+        $uri  = self::APPS_BASE_FEED_URI . self::APPS_GROUP_PATH . '/';
+        $uri .= $this->getDomain() . '/' . $groupId . '/member/' . $memberId;
+
+        return $this->delete($uri);
+    }
+
+    /**
+     * Retrieves all the members of a group
+     *
+     * @param string $groupId The unique id of the group
+     * @return Zend_Gdata_Gapps_MemberFeed Collection of MemberEntry objects
+     *              representing all members apart of the group.
+     */
+    public function retrieveAllMembers($groupId)
+    {
+        return $this->retrieveAllEntriesForFeed(
+                $this->retrievePageOfMembers($groupId));
+    }
+
+    /**
+     * Add an email as an owner of a group
+     *
+     * @param string $email Owner's email
+     * @param string $groupId Group ownership to be checked for
+     * @return Zend_Gdata_Gapps_OwnerEntry The OwnerEntry returned by the server
+     */
+    public function addOwnerToGroup($email, $groupId)
+    {
+        $owner = $this->newOwnerEntry();
+
+        $properties[] = $this->newProperty();
+        $properties[0]->name = 'email';
+        $properties[0]->value = $email;
+
+        $owner->property = $properties;
+
+        $uri  = self::APPS_BASE_FEED_URI . self::APPS_GROUP_PATH . '/';
+        $uri .= $this->getDomain() . '/' . $groupId . '/owner';
+        
+        return $this->insertOwner($owner, $uri);
+    }
+
+    /**
+     * Retrieves all the owners of a group
+     *
+     * @param string $groupId The unique identifier for the group
+     * @return Zend_Gdata_Gapps_OwnerFeed Collection of Zend_Gdata_OwnerEntry
+     *              objects representing all owners apart of the group.
+     */
+    public function retrieveGroupOwners($groupId)
+    {
+        $uri  = self::APPS_BASE_FEED_URI . self::APPS_GROUP_PATH . '/';
+        $uri .= $this->getDomain() . '/' . $groupId . '/owner';
+
+        return $this->getOwnerFeed($uri);
+    }
+
+    /**
+     * Checks to see if an email is an owner of a group
+     *
+     * @param string $email Owner's email
+     * @param string $groupId Group ownership to be checked for
+     * @return bool True, if given entity is an owner
+     */
+    public function isOwner($email, $groupId)
+    {
+        $uri  = self::APPS_BASE_FEED_URI . self::APPS_GROUP_PATH . '/';
+        $uri .= $this->getDomain() . '/' . $groupId . '/owner/' . $email;
+        
+        //if the enitiy is not an owner of the group, an exception is thrown
+        try {            
+            $results = $this->get($uri);
+        } catch (Exception $e) {
+            $results = false;
+        }
+
+        if($results) {
+            return TRUE;
+        } else {
+            return FALSE;
+        }
+    }
+
+    /**
+     * Remove email as an owner of a group
+     *
+     * @param string $email Owner's email
+     * @param string $groupId The unique identifier for the group
+     */
+    public function removeOwnerFromGroup($email, $groupId)
+    {
+        $uri  = self::APPS_BASE_FEED_URI . self::APPS_GROUP_PATH . '/';
+        $uri .= $this->getDomain() . '/' . $groupId . '/owner/' . $email;
+
+        return $this->delete($uri);
+    }
+
+    /**
+     * Update group properties with new values. any property not defined will not
+     * be updated
+     *
+     * @param string $groupId A unique identifier for the group
+     * @param string $groupName The name of the group
+     * @param string $description A description of the group
+     * @param string $emailPermission The subscription permission of the group
+     * @return Zend_Gdata_Gapps_GroupEntry The group entry as updated on the server.
+     */
+    public function updateGroup($groupId, $groupName = null, $description = null,
+            $emailPermission = null)
+    {
+        $i = 0;
+        $group = $this->newGroupEntry();
+        
+        $properties[$i] = $this->newProperty();
+        $properties[$i]->name = 'groupId';
+        $properties[$i]->value = $groupId;
+        $i++;
+
+        if($groupName != null) {
+            $properties[$i] = $this->newProperty();
+            $properties[$i]->name = 'groupName';
+            $properties[$i]->value = $groupName;
+            $i++;
+        }
+
+        if($description != null) {
+            $properties[$i] = $this->newProperty();
+            $properties[$i]->name = 'description';
+            $properties[$i]->value = $description;
+            $i++;
+        }
+
+        if($emailPermission != null) {
+            $properties[$i] = $this->newProperty();
+            $properties[$i]->name = 'emailPermission';
+            $properties[$i]->value = $emailPermission;
+            $i++;
+        }
+        
+        $group->property = $properties;
+
+        $uri  = self::APPS_BASE_FEED_URI . self::APPS_GROUP_PATH . '/';
+        $uri .= $this->getDomain() . '/' . $groupId;
+
+        return $this->updateEntry($group, $uri, 'Zend_Gdata_Gapps_GroupEntry');        
+    }
+
+    /**
+     * Retrieve all of the groups that a user is a member of
+     *
+     * @param string $memberId Member username
+     * @param bool $directOnly (Optional) If true, members with direct association 
+     *             only will be considered
+     * @return Zend_Gdata_Gapps_GroupFeed Collection of Zend_Gdata_GroupEntry
+     *              objects representing all groups member is apart of in the domain.
+     */
+    public function retrieveGroups($memberId, $directOnly = null)
+    {
+        $query = $this->newGroupQuery();
+        $query->setMember($memberId);
+        if($directOnly != null) {
+            $query->setDirectOnly($directOnly);
+        }
+        return $this->getGroupFeed($query);
+    }
+
+    /**
+     * Retrieve a page of groups in alphabetical order, starting with the
+     * provided group.
+     *
+     * @param string $startGroup (optional) The first group to
+     *              retrieve. If null or not defined, the page will begin
+     *              with the first group in the domain.
+     * @return Zend_Gdata_Gapps_GroupFeed Collection of Zend_Gdata_GroupEntry
+     *              objects representing the groups in the domain.
+     * @throws Zend_Gdata_App_Exception
+     * @throws Zend_Gdata_App_HttpException
+     * @throws Zend_Gdata_Gapps_ServiceException
+     */
+    public function retrievePageOfGroups ($startGroup = null)
+    {
+        $query = $this->newGroupQuery();
+        $query->setStartGroupId($startGroup);
+        return $this->getGroupFeed($query);
+    }
+
+    /**
+     * Gets page of Members
+     *
+     * @param string $groupId The group id which should be searched.
+     * @param string $startMember (optinal) The address of the first member,
+     *              or null to start with the first member in the list.
+     * @return Zend_Gdata_Gapps_MemberFeed Collection of Zend_Gdata_MemberEntry
+     *              objects
+     */
+    public function retrievePageOfMembers($groupId, $startMember = null)
+    {
+        $query = $this->newMemberQuery($groupId);
+        $query->setStartMemberId($startMember);
+        return $this->getMemberFeed($query);
+    }
+
+    /**
      * Create a new email list.
      *
      * @param string $emailList The name of the email list to be created.
Index: library/Zend/Gdata/Gapps/MemberEntry.php
===================================================================
--- library/Zend/Gdata/Gapps/MemberEntry.php	(revision 0)
+++ library/Zend/Gdata/Gapps/MemberEntry.php	(revision 0)
@@ -0,0 +1,159 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id:$
+ */
+
+/**
+ * @see Zend_Gdata_Entry
+ */
+require_once 'Zend/Gdata/Entry.php';
+
+/**
+ * @see Zend_Gdata_Gapps_Extension_Property
+ */
+require_once 'Zend/Gdata/Gapps/Extension/Property.php';
+
+/**
+ * Data model class for a Google Apps Member Entry.
+ *
+ * Each member entry describes a single member within a Google Apps hosted
+ * domain.
+ *
+ * To transfer member entries to and from the Google Apps servers, including
+ * creating new entries, refer to the Google Apps service class,
+ * Zend_Gdata_Gapps.
+ *
+ * This class represents <atom:entry> in the Google Data protocol.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Gdata_Gapps_MemberEntry extends Zend_Gdata_Entry
+{
+
+    protected $_entryClassName = 'Zend_Gdata_Gapps_MemberEntry';
+
+    /**
+     * <apps:property> element containing information about other items
+     * relevant to this entry.
+     *
+     * @var Zend_Gdata_Gapps_Extension_Property
+     */
+    protected $_property = array();
+
+    /**
+     * Create a new instance.
+     *
+     * @param DOMElement $element (optional) DOMElement from which this
+     *          object should be constructed.
+     */
+    public function __construct($element = null)
+    {
+        $this->registerAllNamespaces(Zend_Gdata_Gapps::$namespaces);
+        parent::__construct($element);
+    }
+
+    /**
+     * Retrieves a DOMElement which corresponds to this element and all
+     * child properties.  This is used to build an entry back into a DOM
+     * and eventually XML text for application storage/persistence.
+     *
+     * @param DOMDocument $doc The DOMDocument used to construct DOMElements
+     * @return DOMElement The DOMElement representing this element and all
+     *          child properties.
+     */
+    public function getDOM($doc = null, $majorVersion = 1, $minorVersion = null)
+    {
+        $element = parent::getDOM($doc, $majorVersion, $minorVersion);
+
+        foreach ($this->_property as $p) {
+            $element->appendChild($p->getDOM($element->ownerDocument));
+        }
+        return $element;
+    }
+
+    /**
+     * Creates individual Entry objects of the appropriate type and
+     * stores them as members of this entry based upon DOM data.
+     *
+     * @param DOMNode $child The DOMNode to process
+     */
+    protected function takeChildFromDOM($child)
+    {
+        $absoluteNodeName = $child->namespaceURI . ':' . $child->localName;
+
+        switch ($absoluteNodeName) {
+
+            case $this->lookupNamespace('apps') . ':' . 'property';
+                $property = new Zend_Gdata_Gapps_Extension_Property();
+                $property->transferFromDOM($child);
+                $this->_property[] = $property;
+                break;
+            default:
+                parent::takeChildFromDOM($child);
+                break;
+        }
+    }
+
+    /**
+     * Returns all property tags for this entry
+     *
+     * @param string $rel The rel value of the property to be found. If null,
+     *          the array of properties is returned instead.
+     * @return mixed Either an array of Zend_Gdata_Gapps_Extension_Property
+     *          objects if $rel is null, a single
+     *          Zend_Gdata_Gapps_Extension_Property object if $rel is specified
+     *          and a matching feed link is found, or null if $rel is
+     *          specified and no matching property is found.
+     */
+    public function getProperty($rel = null)
+    {
+        if ($rel == null) {
+            return $this->_property;
+        } else {
+            foreach ($this->_property as $p) {
+                if ($p->rel == $rel) {
+                    return $p;
+                }
+            }
+            return null;
+        }
+    }
+
+    /**
+     * Set the value of the  property property for this object.
+     *
+     * @param array $value A collection of
+     *          Zend_Gdata_Gapps_Extension_Property objects.
+     * @return Zend_Gdata_Gapps_MemberEntry Provides a fluent interface.
+     */
+    public function setProperty($value)
+    {
+        $this->_property = $value;
+        return $this;
+    }
+
+}
+
+
Index: library/Zend/Gdata/Gapps/MemberFeed.php
===================================================================
--- library/Zend/Gdata/Gapps/MemberFeed.php	(revision 0)
+++ library/Zend/Gdata/Gapps/MemberFeed.php	(revision 0)
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id:$
+ */
+
+/**
+ * @see Zend_Gdata_Feed
+ */
+require_once 'Zend/Gdata/Feed.php';
+
+/**
+ * @see Zend_Gdata_Gapps_MemberEntry
+ */
+require_once 'Zend/Gdata/Gapps/MemberEntry.php';
+
+/**
+ * Data model for a collection of Google Apps member entries, usually
+ * provided by the Google Apps servers.
+ *
+ * For information on requesting this feed from a server, see the Google
+ * Apps service class, Zend_Gdata_Gapps.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Gdata_Gapps_MemberFeed extends Zend_Gdata_Feed
+{
+
+    protected $_entryClassName = 'Zend_Gdata_Gapps_MemberEntry';
+    protected $_feedClassName = 'Zend_Gdata_Gapps_MemberFeed';
+
+}
Index: library/Zend/Gdata/Gapps/MemberQuery.php
===================================================================
--- library/Zend/Gdata/Gapps/MemberQuery.php	(revision 0)
+++ library/Zend/Gdata/Gapps/MemberQuery.php	(revision 0)
@@ -0,0 +1,194 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id:$
+ */
+
+/**
+ * @see Zend_Gdata_Gapps_Query
+ */
+require_once('Zend/Gdata/Gapps/Query.php');
+
+/**
+ * Assists in constructing queries for Google Apps member entries.
+ * Instances of this class can be provided in many places where a URL is
+ * required.
+ *
+ * For information on submitting queries to a server, see the Google Apps
+ * service class, Zend_Gdata_Gapps.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Gdata_Gapps_MemberQuery extends Zend_Gdata_Gapps_Query
+{
+
+    /**
+     * If not null, specifies the group id
+     *
+     * @var string
+     */
+    protected $_groupId = null;
+
+    /**
+     * If not null, specifies the member id of the user who should be
+     * retrieved by this query.
+     *
+     * @var string
+     */
+    protected $_memberId = null;
+
+    /**
+     * Create a new instance.
+     *
+     * @param string $domain (optional) The Google Apps-hosted domain to use
+     *          when constructing query URIs.
+     * @param string $groupId (optional) Value for the groupId property.
+     * @param string $memberId (optional) Value for the memberId property.
+     * @param string $startMemberId (optional) Value for the
+     *          startMemberId property.
+     */
+    public function __construct($domain = null, $groupId = null, $memberId = null,
+            $startMemberId = null)
+    {
+        parent::__construct($domain);
+        $this->setGroupId($groupId);
+        $this->setMemberId($memberId);
+        $this->setStartMemberId($startMemberId);
+    }
+
+    /**
+     * Set the group id to query for.
+     *
+     * @see getGroupId
+     * @param string $value The group id to filter search results by, or null to
+     *              disable.
+     */
+    public function setGroupId($value)
+    {
+        $this->_groupId = $value;
+    }
+
+    /**
+     * Get the group id to query for. If no group id is set, null will be
+     * returned.
+     *
+     * @param string $value The group id to filter search results by, or
+     *          null if disabled.
+     * @return string The group id
+     */
+    public function getGroupId()
+    {
+        return $this->_groupId;
+    }
+
+
+    /**
+     * Set the member id to query for. When set, only users with a member id
+     * matching this value will be returned in search results. Set to
+     * null to disable filtering by member id.
+     *
+     * @see getMemberId
+     * @param string $value The member id to filter search results by, or null to
+     *              disable.
+     */
+    public function setMemberId($value)
+    {
+        $this->_memberId = $value;
+    }
+
+    /**
+     * Get the member id to query for. If no member id is set, null will be
+     * returned.
+     *
+     * @param string $value The member id to filter search results by, or
+     *          null if disabled.
+     * @return The member id
+     */
+    public function getMemberId()
+    {
+        return $this->_memberId;
+    }
+
+    /**
+     * Set the first member id which should be displayed when retrieving
+     * a list of members.
+     *
+     * @param string $value The first member id to be returned, or null to
+     *          disable.
+     */
+    public function setStartMemberId($value)
+    {
+        if ($value !== null) {
+            $this->_params['start'] = $value;
+        } else {
+            unset($this->_params['start']);
+        }
+    }
+
+    /**
+     * Get the first username which should be displayed when retrieving
+     * a list of users.
+     *
+     * @see setStartUsername
+     * @return string The first username to be returned, or null if
+     *          disabled.
+     */
+    public function getStartMemberId()
+    {
+        if (array_key_exists('start', $this->_params)) {
+            return $this->_params['start'];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the query URL generated by this query instance.
+     *
+     * @return string The query URL for this instance.
+     */
+    public function getQueryUrl()
+    {
+
+        $uri = Zend_Gdata_Gapps::APPS_BASE_FEED_URI;
+        $uri .= Zend_Gdata_Gapps::APPS_GROUP_PATH;
+        $uri .= '/' . $this->_domain;
+        if ($this->_groupId !== null) {
+            $uri .= '/' . $this->_groupId;
+        } else {
+            require_once 'Zend/Gdata/App/InvalidArgumentException.php';
+            throw new Zend_Gdata_App_InvalidArgumentException(
+                    'groupId must not be null');
+        }
+
+        $uri .= '/member';
+
+        if ($this->_memberId !== null) {
+            $uri .= '/' . $this->_memberId;
+        }
+        $uri .= $this->getQueryString();
+        return $uri;
+    }
+
+}
Index: library/Zend/Gdata/Gapps/OwnerEntry.php
===================================================================
--- library/Zend/Gdata/Gapps/OwnerEntry.php	(revision 0)
+++ library/Zend/Gdata/Gapps/OwnerEntry.php	(revision 0)
@@ -0,0 +1,158 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id:$
+ */
+
+/**
+ * @see Zend_Gdata_Entry
+ */
+require_once 'Zend/Gdata/Entry.php';
+
+/**
+ * @see Zend_Gdata_Gapps_Extension_Property
+ */
+require_once 'Zend/Gdata/Gapps/Extension/Property.php';
+
+/**
+ * Data model class for a Google Apps Owner Entry.
+ *
+ * Each owner entry describes a single owner within a Google Apps hosted
+ * domain.
+ *
+ * To transfer owner entries to and from the Google Apps servers, including
+ * creating new entries, refer to the Google Apps service class,
+ * Zend_Gdata_Gapps.
+ *
+ * This class represents <atom:entry> in the Google Data protocol.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Gdata_Gapps_OwnerEntry extends Zend_Gdata_Entry
+{
+
+    protected $_entryClassName = 'Zend_Gdata_Gapps_OwnerEntry';
+
+    /**
+     * <apps:property> element containing information about other items
+     * relevant to this entry.
+     *
+     * @var Zend_Gdata_Gapps_Extension_Property
+     */
+    protected $_property = array();
+
+    /**
+     * Create a new instance.
+     *
+     * @param DOMElement $element (optional) DOMElement from which this
+     *          object should be constructed.
+     */
+    public function __construct($element = null)
+    {
+        $this->registerAllNamespaces(Zend_Gdata_Gapps::$namespaces);
+        parent::__construct($element);
+    }
+
+    /**
+     * Retrieves a DOMElement which corresponds to this element and all
+     * child properties.  This is used to build an entry back into a DOM
+     * and eventually XML text for application storage/persistence.
+     *
+     * @param DOMDocument $doc The DOMDocument used to construct DOMElements
+     * @return DOMElement The DOMElement representing this element and all
+     *          child properties.
+     */
+    public function getDOM($doc = null, $majorVersion = 1, $minorVersion = null)
+    {
+        $element = parent::getDOM($doc, $majorVersion, $minorVersion);
+
+        foreach ($this->_property as $p) {
+            $element->appendChild($p->getDOM($element->ownerDocument));
+        }
+        return $element;
+    }
+
+    /**
+     * Creates individual Entry objects of the appropriate type and
+     * stores them as owners of this entry based upon DOM data.
+     *
+     * @param DOMNode $child The DOMNode to process
+     */
+    protected function takeChildFromDOM($child)
+    {
+        $absoluteNodeName = $child->namespaceURI . ':' . $child->localName;
+
+        switch ($absoluteNodeName) {
+
+            case $this->lookupNamespace('apps') . ':' . 'property';
+                $property = new Zend_Gdata_Gapps_Extension_Property();
+                $property->transferFromDOM($child);
+                $this->_property[] = $property;
+                break;
+            default:
+                parent::takeChildFromDOM($child);
+                break;
+        }
+    }
+
+    /**
+     * Returns all property tags for this entry
+     *
+     * @param string $rel The rel value of the property to be found. If null,
+     *          the array of properties is returned instead.
+     * @return mixed Either an array of Zend_Gdata_Gapps_Extension_Property
+     *          objects if $rel is null, a single
+     *          Zend_Gdata_Gapps_Extension_Property object if $rel is specified
+     *          and a matching feed link is found, or null if $rel is
+     *          specified and no matching property is found.
+     */
+    public function getProperty($rel = null)
+    {
+        if ($rel == null) {
+            return $this->_property;
+        } else {
+            foreach ($this->_property as $p) {
+                if ($p->rel == $rel) {
+                    return $p;
+                }
+            }
+            return null;
+        }
+    }
+
+    /**
+     * Set the value of the  property property for this object.
+     *
+     * @param array $value A collection of
+     *          Zend_Gdata_Gapps_Extension_Property objects.
+     * @return Zend_Gdata_Gapps_OwnerEntry Provides a fluent interface.
+     */
+    public function setProperty($value)
+    {
+        $this->_property = $value;
+        return $this;
+    }
+
+}
+
Index: library/Zend/Gdata/Gapps/GroupEntry.php
===================================================================
--- library/Zend/Gdata/Gapps/GroupEntry.php	(revision 0)
+++ library/Zend/Gdata/Gapps/GroupEntry.php	(revision 0)
@@ -0,0 +1,158 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id:$
+ */
+
+/**
+ * @see Zend_Gdata_Entry
+ */
+require_once 'Zend/Gdata/Entry.php';
+
+/**
+ * @see Zend_Gdata_Gapps_Extension_Property
+ */
+require_once 'Zend/Gdata/Gapps/Extension/Property.php';
+
+/**
+ * Data model class for a Google Apps Group Entry.
+ *
+ * Each group entry describes a single group within a Google Apps hosted
+ * domain.
+ *
+ * To transfer group entries to and from the Google Apps servers, including
+ * creating new entries, refer to the Google Apps service class,
+ * Zend_Gdata_Gapps.
+ *
+ * This class represents <atom:entry> in the Google Data protocol.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Gdata_Gapps_GroupEntry extends Zend_Gdata_Entry
+{
+
+    protected $_entryClassName = 'Zend_Gdata_Gapps_GroupEntry';
+
+    /**
+     * <apps:property> element containing information about other items
+     * relevant to this entry.
+     *
+     * @var Zend_Gdata_Gapps_Extension_Property
+     */
+    protected $_property = array();
+
+    /**
+     * Create a new instance.
+     *
+     * @param DOMElement $element (optional) DOMElement from which this
+     *          object should be constructed.
+     */
+    public function __construct($element = null)
+    {
+        $this->registerAllNamespaces(Zend_Gdata_Gapps::$namespaces);
+        parent::__construct($element);
+    }
+
+    /**
+     * Retrieves a DOMElement which corresponds to this element and all
+     * child properties.  This is used to build an entry back into a DOM
+     * and eventually XML text for application storage/persistence.
+     *
+     * @param DOMDocument $doc The DOMDocument used to construct DOMElements
+     * @return DOMElement The DOMElement representing this element and all
+     *          child properties.
+     */
+    public function getDOM($doc = null, $majorVersion = 1, $minorVersion = null)
+    {
+        $element = parent::getDOM($doc, $majorVersion, $minorVersion);
+
+        foreach ($this->_property as $p) {
+            $element->appendChild($p->getDOM($element->ownerDocument));
+        }
+        return $element;
+    }
+
+    /**
+     * Creates individual Entry objects of the appropriate type and
+     * stores them as members of this entry based upon DOM data.
+     *
+     * @param DOMNode $child The DOMNode to process
+     */
+    protected function takeChildFromDOM($child)
+    {
+        $absoluteNodeName = $child->namespaceURI . ':' . $child->localName;
+
+        switch ($absoluteNodeName) {
+
+            case $this->lookupNamespace('apps') . ':' . 'property';
+                $property = new Zend_Gdata_Gapps_Extension_Property();
+                $property->transferFromDOM($child);
+                $this->_property[] = $property;
+                break;
+            default:
+                parent::takeChildFromDOM($child);
+                break;
+        }
+    }
+
+    /**
+     * Returns all property tags for this entry
+     *
+     * @param string $rel The rel value of the property to be found. If null,
+     *          the array of properties is returned instead.
+     * @return mixed Either an array of Zend_Gdata_Gapps_Extension_Property
+     *          objects if $rel is null, a single
+     *          Zend_Gdata_Gapps_Extension_Property object if $rel is specified
+     *          and a matching feed link is found, or null if $rel is
+     *          specified and no matching property is found.
+     */
+    public function getProperty($rel = null)
+    {
+        if ($rel == null) {
+            return $this->_property;
+        } else {
+            foreach ($this->_property as $p) {
+                if ($p->rel == $rel) {
+                    return $p;
+                }
+            }
+            return null;
+        }
+    }
+
+    /**
+     * Set the value of the  property property for this object.
+     *
+     * @param array $value A collection of
+     *          Zend_Gdata_Gapps_Extension_Property objects.
+     * @return Zend_Gdata_Gapps_GroupEntry Provides a fluent interface.
+     */
+    public function setProperty($value)
+    {
+        $this->_property = $value;
+        return $this;
+    }
+
+}
+
Index: library/Zend/Gdata/Gapps/OwnerFeed.php
===================================================================
--- library/Zend/Gdata/Gapps/OwnerFeed.php	(revision 0)
+++ library/Zend/Gdata/Gapps/OwnerFeed.php	(revision 0)
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id:$
+ */
+
+/**
+ * @see Zend_Gdata_Feed
+ */
+require_once 'Zend/Gdata/Feed.php';
+
+/**
+ * @see Zend_Gdata_Gapps_OwnerEntry
+ */
+require_once 'Zend/Gdata/Gapps/OwnerEntry.php';
+
+/**
+ * Data model for a collection of Google Apps owner entries, usually
+ * provided by the Google Apps servers.
+ *
+ * For information on requesting this feed from a server, see the Google
+ * Apps service class, Zend_Gdata_Gapps.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Gdata_Gapps_OwnerFeed extends Zend_Gdata_Feed
+{
+
+    protected $_entryClassName = 'Zend_Gdata_Gapps_OwnerEntry';
+    protected $_feedClassName = 'Zend_Gdata_Gapps_OwnerFeed';
+
+}
Index: library/Zend/Gdata/Gapps/GroupFeed.php
===================================================================
--- library/Zend/Gdata/Gapps/GroupFeed.php	(revision 0)
+++ library/Zend/Gdata/Gapps/GroupFeed.php	(revision 0)
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id:$
+ */
+
+/**
+ * @see Zend_Gdata_Feed
+ */
+require_once 'Zend/Gdata/Feed.php';
+
+/**
+ * @see Zend_Gdata_Gapps_GroupEntry
+ */
+require_once 'Zend/Gdata/Gapps/GroupEntry.php';
+
+/**
+ * Data model for a collection of Google Apps group entries, usually
+ * provided by the Google Apps servers.
+ *
+ * For information on requesting this feed from a server, see the Google
+ * Apps service class, Zend_Gdata_Gapps.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Gdata_Gapps_GroupFeed extends Zend_Gdata_Feed
+{
+
+    protected $_entryClassName = 'Zend_Gdata_Gapps_GroupEntry';
+    protected $_feedClassName = 'Zend_Gdata_Gapps_GroupFeed';
+
+}
\ No newline at end of file
Index: library/Zend/Gdata/Gapps/OwnerQuery.php
===================================================================
--- library/Zend/Gdata/Gapps/OwnerQuery.php	(revision 0)
+++ library/Zend/Gdata/Gapps/OwnerQuery.php	(revision 0)
@@ -0,0 +1,147 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id:$
+ */
+
+/**
+ * @see Zend_Gdata_Gapps_Query
+ */
+require_once('Zend/Gdata/Gapps/Query.php');
+
+/**
+ * Assists in constructing queries for Google Apps owner entries.
+ * Instances of this class can be provided in many places where a URL is
+ * required.
+ *
+ * For information on submitting queries to a server, see the Google Apps
+ * service class, Zend_Gdata_Gapps.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Gdata_Gapps_OwnerQuery extends Zend_Gdata_Gapps_Query
+{
+
+    /**
+     * Group owner is refering to
+     *
+     * @var string
+     */
+    protected $_groupId = null;
+
+    /**
+     * The email of the owner
+     *
+     * @var string
+     */
+    protected $_ownerEmail = null;
+
+    /**
+     * Create a new instance.
+     *
+     * @param string $domain (optional) The Google Apps-hosted domain to use
+     *          when constructing query URIs.
+     * @param string $groupId (optional) Value for the groupId property.
+     * @param string $ownerEmail (optional) Value for the OwnerEmail property.
+     */
+    public function __construct($domain = null, $groupId = null, $ownerEmail = null)
+    {
+        parent::__construct($domain);
+        $this->setGroupId($groupId);
+        $this->setOwnerEmail($ownerEmail);
+    }
+
+    /**
+     * Set the group id to query for.
+     *
+     * @see getGroupId
+     * @param string $value 
+     */
+    public function setGroupId($value)
+    {
+        $this->_groupId = $value;
+    }
+
+    /**
+     * Get the group id to query for.
+     *
+     * @return string
+     *
+     */
+    public function getGroupId()
+    {
+        return $this->_groupId;
+    }
+
+    /**
+     * Set the owner email to query for.
+     *
+     * @see getOwnerEmail
+     * @param string $value
+     */
+    public function setOwnerEmail($value)
+    {
+        $this->_ownerEmail = $value;
+    }
+
+    /**
+     * Get the owner email to query for.
+     *
+     * @return string
+     *
+     */
+    public function getOwnerEmail()
+    {
+        return $this->_ownerEmail;
+    }
+
+    /**
+     * Returns the query URL generated by this query instance.
+     *
+     * @return string The query URL for this instance.
+     */
+    public function getQueryUrl()
+    {
+        $uri = Zend_Gdata_Gapps::APPS_BASE_FEED_URI;
+        $uri .= Zend_Gdata_Gapps::APPS_GROUP_PATH;
+        $uri .= '/' . $this->_domain;
+        if ($this->_groupId !== null) {
+            $uri .= '/' . $this->_groupId;
+        } else {
+            require_once 'Zend/Gdata/App/InvalidArgumentException.php';
+            throw new Zend_Gdata_App_InvalidArgumentException(
+                    'groupId must not be null');
+        }
+        
+        $uri .= '/owner';
+        
+        if ($this->_ownerEmail !== null) {
+            $uri .= '/' . $this->_ownerEmail;
+        }
+
+        $uri .= $this->getQueryString();
+        return $uri;
+    }
+
+}
Index: library/Zend/Gdata/Gapps/GroupQuery.php
===================================================================
--- library/Zend/Gdata/Gapps/GroupQuery.php	(revision 0)
+++ library/Zend/Gdata/Gapps/GroupQuery.php	(revision 0)
@@ -0,0 +1,226 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id:$
+ */
+
+/**
+ * @see Zend_Gdata_Gapps_Query
+ */
+require_once('Zend/Gdata/Gapps/Query.php');
+
+/**
+ * Assists in constructing queries for Google Apps group entries.
+ * Instances of this class can be provided in many places where a URL is
+ * required.
+ *
+ * For information on submitting queries to a server, see the Google Apps
+ * service class, Zend_Gdata_Gapps.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Gdata_Gapps_GroupQuery extends Zend_Gdata_Gapps_Query
+{
+
+    /**
+     * If not null, specifies the group id of the group who should be
+     * retrieved by this query.
+     *
+     * @var string
+     */
+    protected $_groupId = null;
+
+    /**
+     * Create a new instance.
+     *
+     * @param string $domain (optional) The Google Apps-hosted domain to use
+     *          when constructing query URIs. 
+     * @param string $groupId (optional) Value for the groupId property.
+     * @param string $startGroupName (optional) Value for the
+     *          startGroupName property.
+     */
+    public function __construct($domain = null, $groupId = null,
+            $startGroupId = null)
+    {
+        parent::__construct($domain);
+        $this->setGroupId($groupId);
+        $this->setStartGroupId($startGroupId);
+    }
+
+    /**
+     * Set the group id to query for. When set, only groups with a group id
+     * matching this value will be returned in search results. Set to
+     * null to disable filtering by group id.
+     *
+     * @see getGroupId
+     * @param string $value The group id to filter search results by, or null to
+     *              disable.
+     */
+    public function setGroupId($value)
+    {
+        $this->_groupId = $value;
+    }
+
+    /**
+     * Get the group id to query for. If no group id is set, null will be
+     * returned.
+     *
+     * @param string $value The group id to filter search results by, or
+     *          null if disabled.
+     */
+    public function getGroupId()
+    {
+        return $this->_groupId;
+    }
+
+    /**
+     * Set the member to query for. When set, only subscribers with an
+     * email address matching this value will be returned in search results.
+     * Set to null to disable filtering by username.
+     *
+     * @param string $value The member email address to filter search
+     *              results by, or null to  disable.
+     */
+    public function setMember($value)
+    {
+        if ($value !== null) {
+            $this->_params['member'] = $value;
+        }
+        else {
+            unset($this->_params['member']);
+        }
+    }
+
+    /**
+     * Get the member email address to query for. If no member is set,
+     * null will be returned.
+     *
+     * @see setMember
+     * @return string The member email address to filter search
+     *              results by, or null if disabled.
+     */
+    public function getMember()
+    {
+        if (array_key_exists('member', $this->_params)) {
+            return $this->_params['member'];
+        } else {
+            return null;
+        }
+    }
+
+
+    /**
+     * Sets the query parameter directOnly
+     * @param bool $value
+     */
+    public function setDirectOnly($value)
+    {
+        if ($value !== null) {
+            if($value == true) {
+                $this->_params['directOnly'] = 'true';
+            } else {
+                $this->_params['directOnly'] = 'false';
+            }
+        } else {
+            unset($this->_params['directOnly']);
+        }
+    }
+
+    /**
+     *
+     * @see setDirectOnly
+     * @return bool
+     */
+    public function getDirectOnly()
+    {
+        if (array_key_exists('directOnly', $this->_params)) {
+
+            if($this->_params['directOnly'] == 'true') {
+                return true;
+            } else {
+                return false;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Set the first group id which should be displayed when retrieving
+     * a list of groups.
+     *
+     * @param string $value The first group id to be returned, or null to
+     *          disable.
+     */
+    public function setStartGroupId($value)
+    {
+        if ($value !== null) {
+            $this->_params['start'] = $value;
+        } else {
+            unset($this->_params['start']);
+        }
+    }
+
+    /**
+     * Get the first group id which should be displayed when retrieving
+     * a list of groups.
+     *
+     * @see setStartGroupId
+     * @return string The first group id to be returned, or null if
+     *          disabled.
+     */
+    public function getStartGroupId()
+    {
+        if (array_key_exists('start', $this->_params)) {
+            return $this->_params['start'];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the query URL generated by this query instance.
+     *
+     * @return string The query URL for this instance.
+     */
+    public function getQueryUrl()
+    {
+
+        $uri  = Zend_Gdata_Gapps::APPS_BASE_FEED_URI;
+        $uri .= Zend_Gdata_Gapps::APPS_GROUP_PATH;
+        $uri .= '/' . $this->_domain;
+        
+        if ($this->_groupId !== null) {
+            $uri .= '/' . $this->_groupId;
+        }
+        
+        if(array_key_exists('member', $this->_params)) {
+            $uri .= '/';
+        }
+        
+        $uri .= $this->getQueryString();
+        return $uri;
+    }
+
+}
Index: library/Zend/Gdata/Gapps/Extension/Property.php
===================================================================
--- library/Zend/Gdata/Gapps/Extension/Property.php	(revision 0)
+++ library/Zend/Gdata/Gapps/Extension/Property.php	(revision 0)
@@ -0,0 +1,180 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: EmailList.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+/**
+ * @see Zend_Gdata_Extension
+ */
+require_once 'Zend/Gdata/Extension.php';
+
+/**
+ * @see Zend_Gdata_Gapps
+ */
+require_once 'Zend/Gdata/Gapps.php';
+
+/**
+ * Represents the apps:Property element used by the Apps data API.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Gapps
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Gdata_Gapps_Extension_Property extends Zend_Gdata_Extension
+{
+
+    protected $_rootNamespace = 'apps';
+    protected $_rootElement = 'property';
+
+    /**
+     * The name of the property
+     *
+     * @var string
+     */
+    protected $_name = null;
+
+    /**
+     * The value of the property
+     * @var string
+     */
+    protected $_value = null;
+
+    /**
+     * Constructs a new Zend_Gdata_Gapps_Extension_Property object.
+     *
+     * @param string $name The name of the property
+     * @param string $value The value of the property
+     */
+    public function __construct($name = null, $value = null)
+    {
+        $this->registerAllNamespaces(Zend_Gdata_Gapps::$namespaces);
+        parent::__construct();
+        $this->_name = $name;
+        $this->_value = $value;
+
+    }
+
+
+    /**
+     * Retrieves a DOMElement which corresponds to this element and all
+     * child properties.  This is used to build an entry back into a DOM
+     * and eventually XML text for sending to the server upon updates, or
+     * for application storage/persistence.
+     *
+     * @param DOMDocument $doc The DOMDocument used to construct DOMElements
+     * @return DOMElement The DOMElement representing this element and all
+     * child properties.
+     */
+    public function getDOM($doc = null, $majorVersion = 1, $minorVersion = null)
+    {
+        $element = parent::getDOM($doc, $majorVersion, $minorVersion);
+        if ($this->_name !== null) {
+            $element->setAttribute('name', $this->_name);
+        }
+        if ($this->_value !== null) {
+            $element->setAttribute('value', $this->_value);
+        }
+
+        return $element;
+
+    }
+
+    /**
+     * Given a DOMNode representing an attribute, tries to map the data into
+     * instance members.  If no mapping is defined, the name and value are
+     * stored in an array.
+     *
+     * @param DOMNode $attribute The DOMNode attribute needed to be handled
+     */
+    protected function takeAttributeFromDOM($attribute)
+    {
+        switch ($attribute->localName) {
+        case 'name':
+            $this->_name = $attribute->nodeValue;
+            break;
+        case 'value':
+            $this->_value = $attribute->nodeValue;
+            break;
+        default:
+            parent::takeAttributeFromDOM($attribute);
+        }
+    }
+
+    /**
+     * Get the value for this element's name attribute.
+     *
+     * @see setName
+     * @return string The requested attribute.
+     */
+    public function getName()
+    {
+        return $this->_name;
+    }
+
+    /**
+     * Set the value for this element's name attribute.
+     * @param string $value The desired value for this attribute.
+     * @return Zend_Gdata_Gapps_Extension_Property The element being modified.
+     */
+    public function setName($value)
+    {
+        $this->_name = $value;
+        return $this;
+    }
+
+    /**
+     * Get the value for this element's value attribute.
+     *
+     * @see setName
+     * @return string The requested attribute.
+     */
+    public function getValue()
+    {
+        return $this->_value;
+    }
+
+    /**
+     * Set the value for this element's value attribute.
+     *
+     * @param string $value The desired value for this attribute.
+     * @return Zend_Gdata_Gapps_Extension_Property The element being modified.
+     */
+    public function setValue($value)
+    {
+        $this->_value = $value;
+        return $this;
+    }
+
+    /**
+     * Magic toString method allows using this directly via echo
+     * Works best in PHP >= 4.2.0
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return "Property Name: " . $this->getName() .
+               "\nProperty Value: " . $this->getValue();
+    }
+}
+?>
\ No newline at end of file

