chemistry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fguilla...@apache.org
Subject svn commit: r882549 - in /incubator/chemistry/trunk/chemistry: chemistry-api/src/main/java/org/apache/chemistry/ chemistry-api/src/main/java/org/apache/chemistry/property/ chemistry-api/src/main/java/org/apache/chemistry/repository/ chemistry-api/src/m...
Date Fri, 20 Nov 2009 13:45:31 GMT
Author: fguillaume
Date: Fri Nov 20 13:45:27 2009
New Revision: 882549

URL: http://svn.apache.org/viewvc?rev=882549&view=rev
Log:
CMIS-63: add paging to API and implement it for AtomPub and Simple

Added:
    incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/ListPage.java   (with props)
    incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/Paging.java   (with props)
    incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleListPage.java   (with props)
Removed:
    incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/property/
    incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/repository/
    incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/type/
Modified:
    incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/SPI.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPConnection.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObjectEntryReader.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObjectFeedReader.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/TypeFeedReader.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/Connector.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/DefaultIOProvider.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/HttpClientConnector.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/HttpClientResponse.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/IOProvider.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/Response.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/AbstractFeedReader.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCheckedOutCollection.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISChildrenCollection.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollection.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISQueryFeed.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/AtomPubCMIS.java
    incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java
    incubator/chemistry/trunk/chemistry/chemistry-jcr/src/main/java/org/apache/chemistry/jcr/JcrConnection.java
    incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java

Added: incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/ListPage.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/ListPage.java?rev=882549&view=auto
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/ListPage.java (added)
+++ incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/ListPage.java Fri Nov 20 13:45:27 2009
@@ -0,0 +1,52 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Authors:
+ *     Florent Guillaume, Nuxeo
+ */
+package org.apache.chemistry;
+
+import java.util.List;
+
+/**
+ * A {@link List} with paging information.
+ * <p>
+ * The list is a sublist (a page) of a bigger underlying list, and information
+ * about the page in the underlying list can be retrieved.
+ */
+public interface ListPage<T> extends List<T> {
+
+    /**
+     * Checks whether the underlying list has more items (skipped due to paging)
+     * after those included in the list.
+     * <p>
+     * If {@code true}, a request with a larger {@link Paging#skipCount} or
+     * larger {@link Paging#maxItems} is expected to return additional results.
+     * <p>
+     * A client should never rely on this value to be exact, because the
+     * contents of the repository may change between two calls.
+     */
+    boolean getHasMoreItems();
+
+    /**
+     * Gets the total number of items in the underlying list (ignoring any
+     * paging).
+     * <p>
+     * If not known, this will be {@code -1}.
+     * <p>
+     * A client should never rely on this value to be exact, because the
+     * contents of the repository may change between two calls.
+     */
+    int getNumItems();
+
+}

Propchange: incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/ListPage.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/ListPage.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/Paging.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/Paging.java?rev=882549&view=auto
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/Paging.java (added)
+++ incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/Paging.java Fri Nov 20 13:45:27 2009
@@ -0,0 +1,50 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Authors:
+ *     Florent Guillaume, Nuxeo
+ */
+package org.apache.chemistry;
+
+/**
+ * Paging requested.
+ * <p>
+ * An instance of this class is provided to methods that will return a
+ * {@link ListPage}.
+ */
+public class Paging {
+
+    /**
+     * The maximum number of objects to return, or {@code 0} for a
+     * repository-specific default
+     */
+    public final int maxItems;
+
+    /**
+     * The number of objects to skip in the returned list. {@code 0} means start
+     */
+    public final int skipCount;
+
+    /**
+     * Constructs paging information with the given parameters
+     *
+     * @param maxItems the maximum number of objects to return, or {@code 0} for
+     *            a repository-specific default
+     * @param skipCount the number of objects to skip in the returned list
+     */
+    public Paging(int maxItems, int skipCount) {
+        this.maxItems = maxItems;
+        this.skipCount = skipCount;
+    }
+
+}

Propchange: incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/Paging.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/Paging.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/SPI.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/SPI.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/SPI.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/SPI.java Fri Nov 20 13:45:27 2009
@@ -19,7 +19,6 @@
 import java.io.IOException;
 import java.io.Serializable;
 import java.util.Collection;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -141,8 +140,6 @@
      * If includeAllowableActions is {@code true}, the repository will return
      * the allowable actions for the current user for object as part of the
      * results.
-     * <p>
-     * The return value hasMoreItems is filled if {@code maxItems > 0}.
      *
      * @param folder the folder
      * @param filter the properties filter, or {@code null} for all properties
@@ -151,17 +148,13 @@
      *            included as well
      * @param includeRenditions {@code true} if renditions should be included as
      *            well
-     * @param maxItems the maximum number of objects to return, or {@code 0} for
-     *            a repository-specific default
-     * @param skipCount the skip count
      * @param orderBy an {@code ORDER BY} clause, or {@code null}
-     * @param hasMoreItems a 1-value boolean array to return a flag stating if
-     *            there are more items
+     * @param paging paging information, or {@code null} for a
+     *            repository-specific default
      */
-    List<ObjectEntry> getChildren(ObjectId folder, String filter,
+    ListPage<ObjectEntry> getChildren(ObjectId folder, String filter,
             boolean includeAllowableActions, boolean includeRelationships,
-            boolean includeRenditions, int maxItems, int skipCount,
-            String orderBy, boolean[] hasMoreItems);
+            boolean includeRenditions, String orderBy, Paging paging);
 
     /**
      * Gets the parent of a folder.
@@ -199,23 +192,18 @@
      * <p>
      * If folder is not {@code null}, then the results include only direct
      * children of that folder.
-     * <p>
-     * The return value hasMoreItems is filled if {@code maxItems > 0}.
      *
      * @param folder the folder, or {@code null}
      * @param filter
      * @param includeAllowableActions
      * @param includeRelationships {@code true} if relationships should be
      *            included as well
-     * @param maxItems
-     * @param hasMoreItems a 1-value boolean array to return a flag stating if
-     *            there are more items
-     * @param skipCount
+     * @param paging paging information, or {@code null} for a
+     *            repository-specific default
      */
-    Collection<ObjectEntry> getCheckedOutDocuments(ObjectId folder,
+    ListPage<ObjectEntry> getCheckedOutDocuments(ObjectId folder,
             String filter, boolean includeAllowableActions,
-            boolean includeRelationships, int maxItems, int skipCount,
-            boolean[] hasMoreItems);
+            boolean includeRelationships, Paging paging);
 
     /*
      * ----- Object Services -----
@@ -337,9 +325,8 @@
      *
      * @param object the object
      * @param filter a rendition filter, or {@code null} for none
-     * @param maxItems the maximum number of renditions to return, or {@code 0}
-     *            for a repository-specific default
-     * @param skipCount the skip count
+     * @param paging paging information, or {@code null} for a
+     *            repository-specific default
      * @return the list of renditions
      *
      * @throws UnsupportedOperationException if renditions are not supported
@@ -347,8 +334,7 @@
      * @see Rendition#FILTER_ALL
      * @see Rendition#FILTER_NONE
      */
-    List<Rendition> getRenditions(ObjectId object, String filter, int maxItems,
-            int skipCount);
+    List<Rendition> getRenditions(ObjectId object, String filter, Paging paging);
 
     /**
      * Checks if the document has an associated content stream.
@@ -570,8 +556,6 @@
      * ). If each row in the output table does not correspond to a specific
      * object and includeAllowableActions is {@code true}, then an exception
      * will be thrown.
-     * <p>
-     * The return value hasMoreItems is filled if {@code maxItems > 0}.
      *
      * @param statement the SQL statement
      * @param searchAllVersions {@code true} if all versions (not only that
@@ -581,17 +565,14 @@
      *            included as well
      * @param includeRenditions {@code true} if renditions should be included as
      *            well
-     * @param maxItems the maximum number of objects to return, or {@code 0} for
-     *            a repository-specific default
-     * @param skipCount the skip count
-     * @param hasMoreItems
+     * @param paging paging information, or {@code null} for a
+     *            repository-specific default
      * @return the matching objects
      */
     // TODO returns a result set actually, there may be computed values
-    Collection<ObjectEntry> query(String statement, boolean searchAllVersions,
+    ListPage<ObjectEntry> query(String statement, boolean searchAllVersions,
             boolean includeAllowableActions, boolean includeRelationships,
-            boolean includeRenditions, int maxItems, int skipCount,
-            boolean[] hasMoreItems);
+            boolean includeRenditions, Paging paging);
 
     /**
      * Gets a list of content changes.
@@ -607,23 +588,21 @@
      * The latest change log token for a repository can be acquired via
      * {@link RepositoryInfo#getLatestChangeToken}.
      * <p>
-     * The return value hasMoreItems is filled if {@code maxItems > 0}.
-     * <p>
-     * The return value latestChangeLogToken contains the change token of the last
-     * change event returned by the iterator.
+     * The return value latestChangeLogToken contains the change token of the
+     * last change event returned by the iterator.
      *
      * @param changeLogToken the change log token, or {@code null}
      * @param includeProperties {@code true} if values are returned in the
      *            change events for updated objects
-     * @param maxItems the maximum number of change events to return, or {@code
-     *            0} for a repository-specific default
-     * @return an iterator over the change events
+     * @param paging paging information, or {@code null} for a
+     *            repository-specific default
+     * @return a paged list of change events
      *
      * @see Repository#getInfo
      * @see RepositoryInfo#getLatestChangeLogToken
      */
-    Iterator<ObjectEntry> getChangeLog(String changeLogToken,
-            boolean includeProperties, int maxItems, boolean[] hasMoreItems,
+    ListPage<ObjectEntry> getChangeLog(String changeLogToken,
+            boolean includeProperties, Paging paging,
             String[] latestChangeLogToken);
 
     /*
@@ -736,18 +715,14 @@
      *            sub-type of typeId are to be returned as well
      * @param filter the properties filter, or {@code null} for all properties
      * @param includeAllowableActions {@code true} to include allowable actions
-     * @param maxItems the maximum number of objects to return, or {@code 0} for
-     *            a repository-specific default
-     * @param skipCount the skip count
-     * @param hasMoreItems a 1-value boolean array to return a flag stating if
-     *            there are more items
+     * @param paging paging information, or {@code null} for a
+     *            repository-specific default
      * @return the list of relationships
      */
-    List<ObjectEntry> getRelationships(ObjectId object,
+    ListPage<ObjectEntry> getRelationships(ObjectId object,
             RelationshipDirection direction, String typeId,
             boolean includeSubRelationshipTypes, String filter,
-            String includeAllowableActions, int maxItems, int skipCount,
-            boolean[] hasMoreItems);
+            String includeAllowableActions, Paging paging);
 
     /*
      * ----- Policy Services -----

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPConnection.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPConnection.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPConnection.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPConnection.java Fri Nov 20 13:45:27 2009
@@ -25,8 +25,6 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
@@ -40,8 +38,10 @@
 import org.apache.chemistry.ContentStream;
 import org.apache.chemistry.Document;
 import org.apache.chemistry.Folder;
+import org.apache.chemistry.ListPage;
 import org.apache.chemistry.ObjectEntry;
 import org.apache.chemistry.ObjectId;
+import org.apache.chemistry.Paging;
 import org.apache.chemistry.Policy;
 import org.apache.chemistry.Property;
 import org.apache.chemistry.Relationship;
@@ -60,6 +60,7 @@
 import org.apache.chemistry.atompub.client.connector.Response;
 import org.apache.chemistry.atompub.client.stax.ReadContext;
 import org.apache.chemistry.atompub.client.stax.XmlProperty;
+import org.apache.chemistry.impl.simple.SimpleListPage;
 import org.apache.chemistry.impl.simple.SimpleObjectId;
 
 /**
@@ -183,8 +184,8 @@
     protected void accumulateFolders(ObjectId folder, int depth, String filter,
             boolean includeAllowableActions, List<ObjectEntry> list) {
         List<ObjectEntry> children = getChildren(folder, filter,
-                includeAllowableActions, false, false, Integer.MAX_VALUE, 0,
-                null, new boolean[1]);
+                includeAllowableActions, false, false, null, new Paging(
+                        Integer.MAX_VALUE, 0));
         for (ObjectEntry child : children) {
             if (child.getBaseType() != BaseType.FOLDER) {
                 continue;
@@ -224,50 +225,26 @@
         return resp.getObjectFeed(new ReadContext(this));
     }
 
-    public List<ObjectEntry> getChildren(ObjectId folder, String filter,
+    public ListPage<ObjectEntry> getChildren(ObjectId folder, String filter,
             boolean includeAllowableActions, boolean includeRelationships,
-            boolean includeRenditions, int maxItems, int skipCount,
-            String orderBy, boolean[] hasMoreItems) {
+            boolean includeRenditions, String orderBy, Paging paging) {
         // TODO filter, includeRelationship, includeAllowableActions, orderBy
-        if (maxItems <= 0) {
-            maxItems = DEFAULT_MAX_CHILDREN;
-        }
-        if (skipCount < 0) {
-            skipCount = 0;
-        }
-
         String href = getObjectEntry(folder).getLink(AtomPub.LINK_DOWN,
                 AtomPub.MEDIA_TYPE_ATOM_FEED);
-        Response resp = connector.get(new Request(href));
+        Request req = new Request(href);
+        if (paging != null) {
+            req.setParameter(AtomPubCMIS.PARAM_MAX_ITEMS,
+                    Integer.toString(paging.maxItems));
+            req.setParameter(AtomPubCMIS.PARAM_SKIP_COUNT,
+                    Integer.toString(paging.skipCount));
+        }
+        Response resp = connector.get(req);
         if (!resp.isOk()) {
             throw new ContentManagerException(
                     "Remote server returned error code: "
                             + resp.getStatusCode());
         }
-        List<ObjectEntry> feed = resp.getObjectFeed(new ReadContext(this));
-
-        List<ObjectEntry> result = new LinkedList<ObjectEntry>();
-        hasMoreItems[0] = false;
-        boolean done = false;
-        for (ObjectEntry entry : feed) {
-            // skip
-            if (skipCount > 0) {
-                skipCount--;
-                continue;
-            }
-            // entry is ok
-            if (done) {
-                hasMoreItems[0] = true;
-                break;
-            }
-            result.add(entry);
-            if (result.size() >= maxItems) {
-                done = true;
-                // don't break now, we still have to find out if there are more
-                // non-filtered entries to fill in hasMoreItems
-            }
-        }
-        return result;
+        return resp.getObjectFeed(new ReadContext(this));
     }
 
     public ObjectEntry getFolderParent(ObjectId folder, String filter) {
@@ -308,10 +285,9 @@
         return resp.getObjectFeed(new ReadContext(this));
     }
 
-    public Collection<ObjectEntry> getCheckedOutDocuments(ObjectId folder,
+    public ListPage<ObjectEntry> getCheckedOutDocuments(ObjectId folder,
             String filter, boolean includeAllowableActions,
-            boolean includeRelationships, int maxItems, int skipCount,
-            boolean[] hasMoreItems) {
+            boolean includeRelationships, Paging paging) {
         // TODO Auto-generated method stub
         throw new UnsupportedOperationException();
     }
@@ -462,7 +438,7 @@
     }
 
     public List<Rendition> getRenditions(ObjectId object, String filter,
-            int maxItems, int skipCount) {
+            Paging paging) {
         return Collections.emptyList();
     }
 
@@ -544,27 +520,26 @@
      * ----- Discovery Services -----
      */
 
-    public Collection<ObjectEntry> query(String statement,
+    public ListPage<ObjectEntry> query(String statement,
             boolean searchAllVersions, boolean includeAllowableActions,
             boolean includeRelationships, boolean includeRenditions,
-            int maxItems, int skipCount, boolean[] hasMoreItems) {
+            Paging paging) {
         String href = repository.getCollectionHref(AtomPubCMIS.COL_QUERY);
         Response resp = connector.postQuery(new Request(href), statement,
-                searchAllVersions, maxItems, skipCount, includeAllowableActions);
+                searchAllVersions, includeAllowableActions, paging);
         if (!resp.isOk()) {
             throw new ContentManagerException(
                     "Remote server returned error code: "
                             + resp.getStatusCode());
         }
-        List<ObjectEntry> objects = resp.getObjectFeed(new ReadContext(this));
+        ListPage<ObjectEntry> objects = resp.getObjectFeed(new ReadContext(this));
         return objects;
     }
 
     public Collection<CMISObject> query(String statement,
             boolean searchAllVersions) {
-        boolean[] hasMoreItems = new boolean[1];
-        Collection<ObjectEntry> res = query(statement, searchAllVersions,
-                false, false, false, -1, 0, hasMoreItems);
+        ListPage<ObjectEntry> res = query(statement, searchAllVersions, false,
+                false, false, new Paging(-1, 0));
         List<CMISObject> objects = new ArrayList<CMISObject>(res.size());
         for (ObjectEntry e : res) {
             objects.add(APPObject.construct((APPObjectEntry) e));
@@ -572,12 +547,11 @@
         return objects;
     }
 
-    public Iterator<ObjectEntry> getChangeLog(String changeLogToken,
-            boolean includeProperties, int maxItems, boolean[] hasMoreItems,
+    public ListPage<ObjectEntry> getChangeLog(String changeLogToken,
+            boolean includeProperties, Paging paging,
             String[] latestChangeLogToken) {
-        hasMoreItems[0] = false;
         latestChangeLogToken[0] = null;
-        return Collections.<ObjectEntry> emptyList().iterator();
+        return SimpleListPage.emptyList();
     }
 
     /*
@@ -617,11 +591,10 @@
      * ----- Relationship Services -----
      */
 
-    public List<ObjectEntry> getRelationships(ObjectId object,
+    public ListPage<ObjectEntry> getRelationships(ObjectId object,
             RelationshipDirection direction, String typeId,
             boolean includeSubRelationshipTypes, String filter,
-            String includeAllowableActions, int maxItems, int skipCount,
-            boolean[] hasMoreItems) {
+            String includeAllowableActions, Paging paging) {
         // TODO Auto-generated method stub
         throw new UnsupportedOperationException();
     }

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObjectEntryReader.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObjectEntryReader.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObjectEntryReader.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObjectEntryReader.java Fri Nov 20 13:45:27 2009
@@ -69,8 +69,7 @@
     @Override
     protected void readAtomElement(ReadContext ctx, StaxReader reader,
             APPObjectEntry object) throws XMLStreamException {
-        String name = reader.getLocalName();
-        if ("link".equals(name)) {
+        if (AtomPub.ATOM_LINK.equals(reader.getName())) {
             String rel = reader.getAttributeValue(AtomPub.ATOM_NS, "rel");
             String href = reader.getAttributeValue(AtomPub.ATOM_NS, "href");
             String type = reader.getAttributeValue(AtomPub.ATOM_NS, "type");

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObjectFeedReader.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObjectFeedReader.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObjectFeedReader.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObjectFeedReader.java Fri Nov 20 13:45:27 2009
@@ -16,19 +16,18 @@
  */
 package org.apache.chemistry.atompub.client;
 
-import java.util.ArrayList;
-import java.util.List;
-
+import org.apache.chemistry.ListPage;
 import org.apache.chemistry.ObjectEntry;
 import org.apache.chemistry.atompub.client.stax.AbstractFeedReader;
 import org.apache.chemistry.atompub.client.stax.EntryReader;
+import org.apache.chemistry.impl.simple.SimpleListPage;
 import org.apache.chemistry.xml.stax.StaxReader;
 
 /**
  *
  */
 public class APPObjectFeedReader extends
-        AbstractFeedReader<List<ObjectEntry>, APPObjectEntry> {
+        AbstractFeedReader<ListPage<ObjectEntry>, APPObjectEntry> {
 
     private static APPObjectFeedReader builder = new APPObjectFeedReader();
 
@@ -46,13 +45,24 @@
     }
 
     @Override
-    protected List<ObjectEntry> createFeed(StaxReader reader) {
-        return new ArrayList<ObjectEntry>();
+    protected ListPage<ObjectEntry> createFeed(StaxReader reader) {
+        return new SimpleListPage<ObjectEntry>();
     }
 
     @Override
-    protected void addEntry(List<ObjectEntry> feed, APPObjectEntry entry) {
+    protected void addEntry(ListPage<ObjectEntry> feed, APPObjectEntry entry) {
         feed.add(entry);
     }
 
+    @Override
+    protected void setHasMoreItems(ListPage<ObjectEntry> feed,
+            boolean hasMoreItems) {
+        ((SimpleListPage<ObjectEntry>) feed).setHasMoreItems(hasMoreItems);
+    }
+
+    @Override
+    protected void setNumItems(ListPage<ObjectEntry> feed, int numItems) {
+        ((SimpleListPage<ObjectEntry>) feed).setNumItems(numItems);
+    }
+
 }

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/TypeFeedReader.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/TypeFeedReader.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/TypeFeedReader.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/TypeFeedReader.java Fri Nov 20 13:45:27 2009
@@ -38,13 +38,23 @@
     }
 
     @Override
+    protected TypeManager createFeed(StaxReader reader) {
+        return new SimpleTypeManager();
+    }
+
+    @Override
     protected void addEntry(TypeManager typeManager, APPType type) {
         typeManager.addType(type);
     }
 
     @Override
-    protected TypeManager createFeed(StaxReader reader) {
-        return new SimpleTypeManager();
+    protected void setHasMoreItems(TypeManager typeManager, boolean hasMoreItems) {
+        // nothing
+    }
+
+    @Override
+    protected void setNumItems(TypeManager typeManager, int numItems) {
+        // nothing
     }
 
 }

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/Connector.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/Connector.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/Connector.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/Connector.java Fri Nov 20 13:45:27 2009
@@ -19,6 +19,7 @@
 import java.util.List;
 
 import org.apache.chemistry.ObjectEntry;
+import org.apache.chemistry.Paging;
 import org.apache.chemistry.Repository;
 import org.apache.chemistry.Type;
 import org.apache.chemistry.atompub.client.ContentManagerException;
@@ -63,14 +64,14 @@
             throws ContentManagerException;
 
     Response putQuery(Request req, String query, boolean searchAllVersions,
-            long maxItems, long skipCount, boolean includeAllowableActions)
+            boolean includeAllowableActions, Paging paging)
             throws ContentManagerException;
 
     Response postObject(Request req, ObjectEntry entry)
             throws ContentManagerException;
 
     Response postQuery(Request req, String query, boolean searchAllVersions,
-            long maxItems, long skipCount, boolean includeAllowableActions)
+            boolean includeAllowableActions, Paging paging)
             throws ContentManagerException;
 
 }

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/DefaultIOProvider.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/DefaultIOProvider.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/DefaultIOProvider.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/DefaultIOProvider.java Fri Nov 20 13:45:27 2009
@@ -18,11 +18,11 @@
  */
 package org.apache.chemistry.atompub.client.connector;
 
-import java.util.List;
-
-import org.apache.chemistry.TypeManager;
+import org.apache.chemistry.ListPage;
 import org.apache.chemistry.ObjectEntry;
+import org.apache.chemistry.Paging;
 import org.apache.chemistry.Type;
+import org.apache.chemistry.TypeManager;
 import org.apache.chemistry.atompub.client.APPObjectEntryReader;
 import org.apache.chemistry.atompub.client.APPObjectEntryWriter;
 import org.apache.chemistry.atompub.client.APPObjectFeedReader;
@@ -57,7 +57,7 @@
         return objectReader;
     }
 
-    public FeedReader<List<ObjectEntry>> getObjectFeedReader() {
+    public FeedReader<ListPage<ObjectEntry>> getObjectFeedReader() {
         return objectFeedReader;
     }
 
@@ -78,11 +78,13 @@
     }
 
     public XmlObjectWriter<String> getQueryWriter(boolean searchAllVersions,
-            long maxItems, long skipCount, boolean includeAllowableActions) {
+            boolean includeAllowableActions, Paging paging) {
         QueryWriter queryWriter = new QueryWriter();
         queryWriter.setSearchAllVersions(searchAllVersions);
-        queryWriter.setMaxItems(maxItems);
-        queryWriter.setSkipCount(skipCount);
+        if (paging != null) {
+            queryWriter.setMaxItems(paging.maxItems);
+            queryWriter.setSkipCount(paging.skipCount);
+        }
         queryWriter.setIncludeAllowableActions(includeAllowableActions);
         return queryWriter;
     }

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/HttpClientConnector.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/HttpClientConnector.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/HttpClientConnector.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/HttpClientConnector.java Fri Nov 20 13:45:27 2009
@@ -22,6 +22,7 @@
 import java.util.List;
 
 import org.apache.chemistry.ObjectEntry;
+import org.apache.chemistry.Paging;
 import org.apache.chemistry.Repository;
 import org.apache.chemistry.Type;
 import org.apache.chemistry.atompub.client.ContentManagerException;
@@ -212,10 +213,10 @@
     }
 
     public Response putQuery(Request req, String query,
-            boolean searchAllVersions, long maxItems, long skipCount,
-            boolean includeAllowableActions) throws ContentManagerException {
-        return put(req, io.getQueryWriter(searchAllVersions, maxItems,
-                skipCount, includeAllowableActions), query);
+            boolean searchAllVersions, boolean includeAllowableActions,
+            Paging paging) throws ContentManagerException {
+        return put(req, io.getQueryWriter(searchAllVersions,
+                includeAllowableActions, paging), query);
     }
 
     public Response postObject(Request req, ObjectEntry entry)
@@ -224,10 +225,10 @@
     }
 
     public Response postQuery(Request req, String query,
-            boolean searchAllVersions, long maxItems, long skipCount,
-            boolean includeAllowableActions) throws ContentManagerException {
-        return post(req, io.getQueryWriter(searchAllVersions, maxItems,
-                skipCount, includeAllowableActions), query);
+            boolean searchAllVersions, boolean includeAllowableActions,
+            Paging paging) throws ContentManagerException {
+        return post(req, io.getQueryWriter(searchAllVersions,
+                includeAllowableActions, paging), query);
     }
 
     public static class XmlObjectWriterRequestEntity<T> implements

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/HttpClientResponse.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/HttpClientResponse.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/HttpClientResponse.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/HttpClientResponse.java Fri Nov 20 13:45:27 2009
@@ -19,14 +19,14 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.List;
 
 import javax.xml.stream.XMLStreamException;
 
-import org.apache.chemistry.TypeManager;
+import org.apache.chemistry.ListPage;
 import org.apache.chemistry.ObjectEntry;
 import org.apache.chemistry.Repository;
 import org.apache.chemistry.Type;
+import org.apache.chemistry.TypeManager;
 import org.apache.chemistry.atompub.client.ContentManagerException;
 import org.apache.chemistry.atompub.client.stax.ReadContext;
 import org.apache.commons.httpclient.Header;
@@ -145,7 +145,7 @@
         }
     }
 
-    public List<ObjectEntry> getObjectFeed(ReadContext ctx)
+    public ListPage<ObjectEntry> getObjectFeed(ReadContext ctx)
             throws ContentManagerException {
         try {
             return io.getObjectFeedReader().read(ctx, getStream());

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/IOProvider.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/IOProvider.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/IOProvider.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/IOProvider.java Fri Nov 20 13:45:27 2009
@@ -17,11 +17,11 @@
  */
 package org.apache.chemistry.atompub.client.connector;
 
-import java.util.List;
-
-import org.apache.chemistry.TypeManager;
+import org.apache.chemistry.ListPage;
 import org.apache.chemistry.ObjectEntry;
+import org.apache.chemistry.Paging;
 import org.apache.chemistry.Type;
+import org.apache.chemistry.TypeManager;
 import org.apache.chemistry.atompub.client.stax.EntryReader;
 import org.apache.chemistry.atompub.client.stax.FeedReader;
 import org.apache.chemistry.atompub.client.stax.ServiceDocumentReader;
@@ -39,13 +39,13 @@
 
     ServiceDocumentReader<?> getServiceDocumentReader();
 
-    FeedReader<List<ObjectEntry>> getObjectFeedReader();
+    FeedReader<ListPage<ObjectEntry>> getObjectFeedReader();
 
     FeedReader<TypeManager> getTypeFeedReader();
 
     XmlObjectWriter<ObjectEntry> getObjectEntryWriter();
 
     XmlObjectWriter<String> getQueryWriter(boolean searchAllVersions,
-            long maxItems, long skipCount, boolean includeAllowableActions);
+            boolean includeAllowableActions, Paging paging);
 
 }

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/Response.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/Response.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/Response.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/connector/Response.java Fri Nov 20 13:45:27 2009
@@ -17,12 +17,12 @@
 package org.apache.chemistry.atompub.client.connector;
 
 import java.io.InputStream;
-import java.util.List;
 
-import org.apache.chemistry.TypeManager;
+import org.apache.chemistry.ListPage;
 import org.apache.chemistry.ObjectEntry;
 import org.apache.chemistry.Repository;
 import org.apache.chemistry.Type;
+import org.apache.chemistry.TypeManager;
 import org.apache.chemistry.atompub.client.ContentManagerException;
 import org.apache.chemistry.atompub.client.stax.ReadContext;
 
@@ -48,7 +48,7 @@
 
     String getString() throws ContentManagerException;
 
-    List<ObjectEntry> getObjectFeed(ReadContext ctx)
+    ListPage<ObjectEntry> getObjectFeed(ReadContext ctx)
             throws ContentManagerException;
 
     TypeManager getTypeFeed(ReadContext ctx) throws ContentManagerException;

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/AbstractFeedReader.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/AbstractFeedReader.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/AbstractFeedReader.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/AbstractFeedReader.java Fri Nov 20 13:45:27 2009
@@ -26,6 +26,7 @@
 import javax.xml.stream.XMLStreamException;
 
 import org.apache.chemistry.atompub.AtomPub;
+import org.apache.chemistry.atompub.AtomPubCMIS;
 import org.apache.chemistry.xml.stax.ChildrenNavigator;
 import org.apache.chemistry.xml.stax.StaxReader;
 
@@ -40,6 +41,10 @@
 
     protected abstract void addEntry(T feed, E entry);
 
+    protected abstract void setHasMoreItems(T feed, boolean hasMoreItems);
+
+    protected abstract void setNumItems(T feed, int numItems);
+
     protected AbstractFeedReader(EntryReader<E> entryBuilder) {
         this.entryBuilder = entryBuilder;
     }
@@ -100,11 +105,18 @@
         while (nav.next() && !isDone(ctx, reader)) {
             String nsUri = reader.getNamespaceURI();
             if (AtomPub.ATOM_NS.equals(nsUri)) {
-                if ("entry".equals(reader.getLocalName())) {
+                if (AtomPub.ATOM_ENTRY.equals(reader.getName())) {
                     addEntry(feed, entryBuilder.read(ctx, reader));
                 } else {
                     readAtomElement(ctx, reader, nsUri, feed);
                 }
+            } else if (AtomPubCMIS.NUM_ITEMS.equals(reader.getName())) {
+                String text = reader.getElementText();
+                try {
+                    setNumItems(feed, Integer.parseInt(text));
+                } catch (NumberFormatException e) {
+                    throw new XMLStreamException("Bad cmisra:numItems: " + e, e);
+                }
             } else {
                 readExtensionElement(ctx, reader, nsUri, feed);
             }
@@ -119,6 +131,12 @@
 
     protected void readAtomElement(ReadContext ctx, StaxReader reader,
             String nsUri, T feed) throws XMLStreamException {
+        if (AtomPub.ATOM_LINK.equals(reader.getName())) {
+            String rel = reader.getAttributeValue(AtomPub.ATOM_NS, "rel");
+            if (AtomPub.LINK_NEXT.equals(rel)) {
+                setHasMoreItems(feed, true);
+            }
+        }
     }
 
     protected void readExtensionElement(ReadContext ctx, StaxReader reader,

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCheckedOutCollection.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCheckedOutCollection.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCheckedOutCollection.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCheckedOutCollection.java Fri Nov 20 13:45:27 2009
@@ -17,14 +17,14 @@
  */
 package org.apache.chemistry.atompub.server;
 
-import java.util.Collection;
-
 import org.apache.abdera.model.Feed;
 import org.apache.abdera.protocol.server.RequestContext;
 import org.apache.abdera.protocol.server.Target;
 import org.apache.abdera.protocol.server.context.ResponseContextException;
+import org.apache.chemistry.ListPage;
 import org.apache.chemistry.ObjectEntry;
 import org.apache.chemistry.ObjectId;
+import org.apache.chemistry.Paging;
 import org.apache.chemistry.Repository;
 import org.apache.chemistry.SPI;
 import org.apache.chemistry.atompub.AtomPub;
@@ -62,21 +62,19 @@
             throws ResponseContextException {
         SPI spi = repository.getSPI(); // TODO XXX connection leak
         Target target = request.getTarget();
-        ObjectId folderId = target.getParameter(AtomPubCMIS.PARAM_FOLDER_ID) == null ? null
-                : spi.newObjectId(target.getParameter(AtomPubCMIS.PARAM_FOLDER_ID));
+        String folderIdString = target.getParameter(AtomPubCMIS.PARAM_FOLDER_ID);
+        ObjectId folderId = folderIdString == null ? null
+                : spi.newObjectId(folderIdString);
         String filter = target.getParameter(AtomPubCMIS.PARAM_FILTER);
-        int maxItems = target.getParameter(AtomPubCMIS.PARAM_MAX_ITEMS) == null ? 0
-                : Integer.parseInt(target.getParameter(AtomPubCMIS.PARAM_MAX_ITEMS));
-        int skipCount = target.getParameter(AtomPubCMIS.PARAM_SKIP_COUNT) == null ? 0
-                : Integer.parseInt(target.getParameter(AtomPubCMIS.PARAM_SKIP_COUNT));
-        boolean includeAllowableActions = target.getParameter(AtomPubCMIS.PARAM_INCLUDE_ALLOWABLE_ACTIONS) == null ? false
-                : Boolean.parseBoolean(target.getParameter(AtomPubCMIS.PARAM_INCLUDE_ALLOWABLE_ACTIONS));
-        boolean includeRelationships = target.getParameter(AtomPubCMIS.PARAM_INCLUDE_RELATIONSHIPS) == null ? false
-                : Boolean.parseBoolean(target.getParameter(AtomPubCMIS.PARAM_INCLUDE_RELATIONSHIPS));
-        boolean[] hasMoreItems = new boolean[1];
-        Collection<ObjectEntry> objectEntries = spi.getCheckedOutDocuments(
+        int maxItems = getParameter(request, AtomPubCMIS.PARAM_MAX_ITEMS, 0);
+        int skipCount = getParameter(request, AtomPubCMIS.PARAM_SKIP_COUNT, 0);
+        boolean includeAllowableActions = getParameter(request,
+                AtomPubCMIS.PARAM_INCLUDE_ALLOWABLE_ACTIONS, false);
+        boolean includeRelationships = getParameter(request,
+                AtomPubCMIS.PARAM_INCLUDE_RELATIONSHIPS, false);
+        ListPage<ObjectEntry> objectEntries = spi.getCheckedOutDocuments(
                 folderId, filter, includeAllowableActions,
-                includeRelationships, maxItems, skipCount, hasMoreItems);
+                includeRelationships, new Paging(maxItems, skipCount));
         return objectEntries;
     }
 

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISChildrenCollection.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISChildrenCollection.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISChildrenCollection.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISChildrenCollection.java Fri Nov 20 13:45:27 2009
@@ -17,19 +17,30 @@
  */
 package org.apache.chemistry.atompub.server;
 
+import java.util.Date;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
+import org.apache.abdera.i18n.iri.IRI;
+import org.apache.abdera.model.Entry;
 import org.apache.abdera.model.Feed;
+import org.apache.abdera.parser.stax.FOMFeed;
 import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
 import org.apache.abdera.protocol.server.Target;
 import org.apache.abdera.protocol.server.context.ResponseContextException;
+import org.apache.axiom.om.OMElement;
+import org.apache.chemistry.ListPage;
 import org.apache.chemistry.ObjectEntry;
 import org.apache.chemistry.ObjectId;
+import org.apache.chemistry.Paging;
 import org.apache.chemistry.Property;
 import org.apache.chemistry.Repository;
 import org.apache.chemistry.SPI;
 import org.apache.chemistry.atompub.AtomPub;
 import org.apache.chemistry.atompub.AtomPubCMIS;
+import org.apache.chemistry.impl.simple.SimpleListPage;
 
 /**
  * CMIS Collection for the children of an object.
@@ -41,12 +52,23 @@
     }
 
     /*
-     * ----- AbstractCollectionAdapter -----
+     * ----- AbstractEntityCollectionAdapter -----
      */
 
     @Override
-    protected Feed createFeedBase(RequestContext request)
-            throws ResponseContextException {
+    public ResponseContext getFeed(RequestContext request) {
+        try {
+            ListPage<ObjectEntry> entries = getEntries(request);
+            Feed feed = createFeedBase(entries, request);
+            addFeedDetails(feed, entries, request);
+            return buildGetFeedResponse(feed);
+        } catch (ResponseContextException e) {
+            return createErrorResponse(e);
+        }
+    }
+
+    protected Feed createFeedBase(ListPage<ObjectEntry> entries,
+            RequestContext request) throws ResponseContextException {
         Feed feed = super.createFeedBase(request);
 
         feed.addLink(getChildrenLink(id, request), AtomPub.LINK_SELF,
@@ -66,46 +88,91 @@
         }
         spi.close();
 
-        // RFC 5005 paging
+        // AtomPub paging
+        // next
+        if (entries.getHasMoreItems()) {
+            // find next skipCount
+            int skipCount = getParameter(request, AtomPubCMIS.PARAM_SKIP_COUNT,
+                    0);
+            skipCount += entries.size();
+            // compute new URI
+            String uri = request.getUri().toString();
+            Pattern pat = Pattern.compile("(.*[?&]"
+                    + AtomPubCMIS.PARAM_SKIP_COUNT + "=)(-?[0-9]+)(.*)");
+            Matcher m = pat.matcher(uri);
+            if (m.matches()) {
+                uri = m.group(1) + skipCount + m.group(3);
+            } else {
+                // unexpected URI...
+            }
+            feed.addLink(uri, AtomPub.LINK_NEXT, AtomPub.MEDIA_TYPE_ATOM_FEED,
+                    null, null, -1);
+        }
+        // TODO prev, first, last
+
+        // CMIS paging: numItems
+        int numItems = entries.getNumItems();
+        if (numItems != -1) {
+            FOMFeed fomFeed = (FOMFeed) feed;
+            OMElement el = fomFeed.getOMFactory().createOMElement(
+                    AtomPubCMIS.NUM_ITEMS);
+            el.setText(Integer.toString(numItems));
+            fomFeed.addChild(el);
+        }
+
         return feed;
     }
 
-    /*
-     * ----- AbstractEntityCollectionAdapter -----
-     */
+    protected void addFeedDetails(Feed feed, ListPage<ObjectEntry> entries,
+            RequestContext request) throws ResponseContextException {
+        feed.setUpdated(new Date()); // TODO
+        if (entries != null) {
+            for (ObjectEntry entryObj : entries) {
+                Entry e = feed.addEntry();
+                IRI feedIri = new IRI(getFeedIriForEntry(entryObj, request));
+                addEntryDetails(request, e, feedIri, entryObj);
+
+                if (isMediaEntry(entryObj)) {
+                    addMediaContent(feedIri, e, entryObj, request);
+                } else {
+                    addContent(e, entryObj, request);
+                }
+            }
+        }
+    }
 
     @Override
-    public Iterable<ObjectEntry> getEntries(RequestContext request)
+    public ListPage<ObjectEntry> getEntries(RequestContext request)
             throws ResponseContextException {
         SPI spi = repository.getSPI(); // TODO XXX connection leak
         ObjectId objectId = spi.newObjectId(id);
         Target target = request.getTarget();
         String filter = target.getParameter(AtomPubCMIS.PARAM_FILTER);
-        boolean includeAllowableActions = target.getParameter(AtomPubCMIS.PARAM_INCLUDE_ALLOWABLE_ACTIONS) == null ? false
-                : Boolean.parseBoolean(target.getParameter(AtomPubCMIS.PARAM_INCLUDE_ALLOWABLE_ACTIONS));
-        boolean includeRelationships = target.getParameter(AtomPubCMIS.PARAM_INCLUDE_RELATIONSHIPS) == null ? false
-                : Boolean.parseBoolean(target.getParameter(AtomPubCMIS.PARAM_INCLUDE_RELATIONSHIPS));
+        boolean includeAllowableActions = getParameter(request,
+                AtomPubCMIS.PARAM_INCLUDE_ALLOWABLE_ACTIONS, false);
+        boolean includeRelationships = getParameter(request,
+                AtomPubCMIS.PARAM_INCLUDE_RELATIONSHIPS, false);
         // TODO proper renditionFilter use
         boolean includeRenditions = target.getParameter(AtomPubCMIS.PARAM_RENDITION_FILTER) == null ? false
                 : true;
         String orderBy = target.getParameter(AtomPubCMIS.PARAM_ORDER_BY);
         if ("descendants".equals(getType())) {
-            int depth = target.getParameter(AtomPubCMIS.PARAM_DEPTH) == null ? 1
-                    : Integer.parseInt(target.getParameter(AtomPubCMIS.PARAM_DEPTH));
+            int depth = getParameter(request, AtomPubCMIS.PARAM_DEPTH, 1);
             List<ObjectEntry> descendants = spi.getDescendants(objectId, depth,
                     filter, includeAllowableActions, includeRelationships,
                     includeRenditions, orderBy);
-            return descendants;
+            SimpleListPage<ObjectEntry> page = new SimpleListPage<ObjectEntry>(
+                    descendants);
+            page.setHasMoreItems(false);
+            page.setNumItems(page.size());
+            return page;
         } else {
-            int maxItems = target.getParameter(AtomPubCMIS.PARAM_MAX_ITEMS) == null ? 0
-                    : Integer.parseInt(target.getParameter(AtomPubCMIS.PARAM_MAX_ITEMS));
-            int skipCount = target.getParameter(AtomPubCMIS.PARAM_SKIP_COUNT) == null ? 0
-                    : Integer.parseInt(target.getParameter(AtomPubCMIS.PARAM_SKIP_COUNT));
-            boolean[] hasMoreItems = new boolean[1];
-            List<ObjectEntry> children = spi.getChildren(objectId, filter,
+            int maxItems = getParameter(request, AtomPubCMIS.PARAM_MAX_ITEMS, 0);
+            int skipCount = getParameter(request, AtomPubCMIS.PARAM_SKIP_COUNT,
+                    0);
+            ListPage<ObjectEntry> children = spi.getChildren(objectId, filter,
                     includeAllowableActions, includeRelationships,
-                    includeRenditions, maxItems, skipCount, orderBy,
-                    hasMoreItems);
+                    includeRenditions, orderBy, new Paging(maxItems, skipCount));
             return children;
         }
     }

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollection.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollection.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollection.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISCollection.java Fri Nov 20 13:45:27 2009
@@ -56,6 +56,21 @@
     }
 
     /*
+     * ----- Helpers -----
+     */
+
+    public static int getParameter(RequestContext request, String name, int def) {
+        String value = request.getTarget().getParameter(name);
+        return value == null ? def : Integer.parseInt(value);
+    }
+
+    public static boolean getParameter(RequestContext request, String name,
+            boolean def) {
+        String value = request.getTarget().getParameter(name);
+        return value == null ? def : Boolean.parseBoolean(value);
+    }
+
+    /*
      * ----- Transactional -----
      */
 

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISQueryFeed.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISQueryFeed.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISQueryFeed.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISQueryFeed.java Fri Nov 20 13:45:27 2009
@@ -16,8 +16,6 @@
  */
 package org.apache.chemistry.atompub.server;
 
-import java.util.Collection;
-
 import org.apache.abdera.model.Element;
 import org.apache.abdera.protocol.server.ProviderHelper;
 import org.apache.abdera.protocol.server.RequestContext;
@@ -25,7 +23,9 @@
 import org.apache.abdera.protocol.server.TargetType;
 import org.apache.abdera.protocol.server.context.ResponseContextException;
 import org.apache.axiom.om.OMDocument;
+import org.apache.chemistry.ListPage;
 import org.apache.chemistry.ObjectEntry;
+import org.apache.chemistry.Paging;
 import org.apache.chemistry.Repository;
 import org.apache.chemistry.SPI;
 import org.apache.chemistry.atompub.AtomPubCMIS;
@@ -99,11 +99,9 @@
         boolean includeRenditions = false;
         int maxItems = -1;
         int skipCount = 0;
-        boolean[] hasMoreItems = new boolean[1];
-        Collection<ObjectEntry> results = spi.query(statement,
-                searchAllVersions, includeAllowableActions,
-                includeRelationships, includeRenditions, maxItems, skipCount,
-                hasMoreItems);
+        ListPage<ObjectEntry> results = spi.query(statement, searchAllVersions,
+                includeAllowableActions, includeRelationships,
+                includeRenditions, new Paging(maxItems, skipCount));
         return results;
     }
 

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/AtomPubCMIS.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/AtomPubCMIS.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/AtomPubCMIS.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/AtomPubCMIS.java Fri Nov 20 13:45:27 2009
@@ -65,6 +65,8 @@
 
     public static final QName CHILDREN = CMISRAName("children");
 
+    public static final QName NUM_ITEMS = CMISRAName("numItems");
+
     public static final QName CONTENT = CMISRAName("content");
 
     public static final QName BASE64 = CMISRAName("base64");

Modified: incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java Fri Nov 20 13:45:27 2009
@@ -23,7 +23,6 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -47,8 +46,10 @@
 import org.apache.chemistry.ContentStreamPresence;
 import org.apache.chemistry.Document;
 import org.apache.chemistry.Folder;
+import org.apache.chemistry.ListPage;
 import org.apache.chemistry.ObjectEntry;
 import org.apache.chemistry.ObjectId;
+import org.apache.chemistry.Paging;
 import org.apache.chemistry.Policy;
 import org.apache.chemistry.Property;
 import org.apache.chemistry.PropertyDefinition;
@@ -162,9 +163,8 @@
      */
     protected void accumulateFolders(ObjectId folder, int depth, String filter,
             boolean includeAllowableActions, List<ObjectEntry> list) {
-        List<ObjectEntry> children = getChildren(folder, filter,
-                includeAllowableActions, false, false, Integer.MAX_VALUE, 0,
-                null, new boolean[1]);
+        ListPage<ObjectEntry> children = getChildren(folder, filter,
+                includeAllowableActions, false, false, null, null);
         for (ObjectEntry child : children) {
             if (child.getBaseType() != BaseType.FOLDER) {
                 continue;
@@ -196,8 +196,7 @@
         // TODO deal with paging properly
         List<ObjectEntry> children = getChildren(folder, filter,
                 includeAllowableActions, includeRelationships,
-                includeRenditions, Integer.MAX_VALUE, 0, orderBy,
-                new boolean[1]);
+                includeRenditions, orderBy, null);
         for (ObjectEntry child : children) {
             list.add(child);
             if (depth > 1 && child.getBaseType() == BaseType.FOLDER) {
@@ -218,10 +217,9 @@
         return list;
     }
 
-    public List<ObjectEntry> getChildren(ObjectId folder, String filter,
+    public ListPage<ObjectEntry> getChildren(ObjectId folder, String filter,
             boolean includeAllowableActions, boolean includeRelationships,
-            boolean includeRenditions, int maxItems, int skipCount,
-            String orderBy, boolean[] hasMoreItems) {
+            boolean includeRenditions, String orderBy, Paging paging) {
         // TODO orderBy
         Set<String> ids = repository.children.get(folder.getId());
         List<ObjectEntry> all = new ArrayList<ObjectEntry>(ids.size());
@@ -229,33 +227,42 @@
             SimpleData data = repository.datas.get(id);
             all.add(new SimpleObjectEntry(data, this));
         }
-        return subList(all, maxItems, skipCount, hasMoreItems);
+        return getListPage(all, paging);
     }
 
     /**
-     * Extracts part of a list according to given parameters.
+     * Extracts part of a list according to given paging parameters.
+     *
+     * @param all the complete list
+     * @param paging the paging info, which may be {@code null}
+     * @return the page
      */
-    protected static List<ObjectEntry> subList(List<ObjectEntry> all,
-            int maxItems, int skipCount, boolean[] hasMoreItems) {
+    public static ListPage<ObjectEntry> getListPage(List<ObjectEntry> all,
+            Paging paging) {
         int total = all.size();
-        int fromIndex = skipCount;
+        int fromIndex = paging == null ? 0 : paging.skipCount;
         if (fromIndex < 0 || fromIndex > total) {
-            hasMoreItems[0] = false;
-            return Collections.emptyList();
+            return SimpleListPage.emptyList();
         }
+        int maxItems = paging == null ? -1 : paging.maxItems;
         if (maxItems <= 0) {
             maxItems = total;
         }
-        int toIndex = skipCount + maxItems;
+        int toIndex = fromIndex + maxItems;
         if (toIndex > total) {
             toIndex = total;
         }
-        hasMoreItems[0] = toIndex < total;
+        List<ObjectEntry> slice;
         if (fromIndex == 0 && toIndex == total) {
-            return all;
+            slice = all;
         } else {
-            return all.subList(fromIndex, toIndex);
+            slice = all.subList(fromIndex, toIndex);
         }
+        SimpleListPage<ObjectEntry> page;
+        page = new SimpleListPage<ObjectEntry>(slice);
+        page.setHasMoreItems(toIndex < total);
+        page.setNumItems(total);
+        return page;
     }
 
     public ObjectEntry getFolderParent(ObjectId folder, String filter) {
@@ -294,10 +301,9 @@
         return parents;
     }
 
-    public Collection<ObjectEntry> getCheckedOutDocuments(ObjectId folder,
+    public ListPage<ObjectEntry> getCheckedOutDocuments(ObjectId folder,
             String filter, boolean includeAllowableActions,
-            boolean includeRelationships, int maxItems, int skipCount,
-            boolean[] hasMoreItems) {
+            boolean includeRelationships, Paging paging) {
         // TODO Auto-generated method stub
         throw new UnsupportedOperationException();
     }
@@ -551,9 +557,9 @@
         }
     }
 
-    public List<Rendition> getRenditions(ObjectId object, String filter,
-            int maxItems, int skipCount) {
-        return Collections.emptyList();
+    public ListPage<Rendition> getRenditions(ObjectId object, String filter,
+            Paging paging) {
+        return SimpleListPage.emptyList();
     }
 
     public boolean hasContentStream(ObjectId document) {
@@ -731,10 +737,10 @@
      * ----- Discovery Services -----
      */
 
-    public Collection<ObjectEntry> query(String statement,
+    public ListPage<ObjectEntry> query(String statement,
             boolean searchAllVersions, boolean includeAllowableActions,
             boolean includeRelationships, boolean includeRenditions,
-            int maxItems, int skipCount, boolean[] hasMoreItems) {
+            Paging paging) {
         // this implementation doesn't try to be very efficient...
         List<ObjectEntry> all = new ArrayList<ObjectEntry>();
         String tableName = null;
@@ -757,7 +763,7 @@
                 all.add(new SimpleObjectEntry(data, this));
             }
         }
-        return subList(all, maxItems, skipCount, hasMoreItems);
+        return getListPage(all, paging);
     }
 
     protected boolean typeMatches(String tableName, String typeId) {
@@ -792,9 +798,8 @@
 
     public Collection<CMISObject> query(String statement,
             boolean searchAllVersions) {
-        boolean[] hasMoreItems = new boolean[1];
-        Collection<ObjectEntry> res = query(statement, searchAllVersions,
-                false, false, false, 0, 0, hasMoreItems);
+        ListPage<ObjectEntry> res = query(statement, searchAllVersions, false,
+                false, false, null);
         List<CMISObject> objects = new ArrayList<CMISObject>(res.size());
         for (ObjectEntry e : res) {
             objects.add(SimpleObject.construct((SimpleObjectEntry) e));
@@ -802,12 +807,11 @@
         return objects;
     }
 
-    public Iterator<ObjectEntry> getChangeLog(String changeLogToken,
-            boolean includeProperties, int maxItems, boolean[] hasMoreItems,
+    public ListPage<ObjectEntry> getChangeLog(String changeLogToken,
+            boolean includeProperties, Paging paging,
             String[] latestChangeLogToken) {
-        hasMoreItems[0] = false;
         latestChangeLogToken[0] = null;
-        return Collections.<ObjectEntry> emptyList().iterator();
+        return SimpleListPage.emptyList();
     }
 
     /*
@@ -847,11 +851,10 @@
      * ----- Relationship Services -----
      */
 
-    public List<ObjectEntry> getRelationships(ObjectId object,
+    public ListPage<ObjectEntry> getRelationships(ObjectId object,
             RelationshipDirection direction, String typeId,
             boolean includeSubRelationshipTypes, String filter,
-            String includeAllowableActions, int maxItems, int skipCount,
-            boolean[] hasMoreItems) {
+            String includeAllowableActions, Paging paging) {
         // TODO Auto-generated method stub
         throw new UnsupportedOperationException();
     }

Added: incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleListPage.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleListPage.java?rev=882549&view=auto
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleListPage.java (added)
+++ incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleListPage.java Fri Nov 20 13:45:27 2009
@@ -0,0 +1,124 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Authors:
+ *     Florent Guillaume, Nuxeo
+ */
+package org.apache.chemistry.impl.simple;
+
+import java.io.Serializable;
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.RandomAccess;
+
+import org.apache.chemistry.ListPage;
+
+/**
+ * A simple implementation of {@link ListPage} based on {@link ArrayList}.
+ */
+public class SimpleListPage<T> extends ArrayList<T> implements ListPage<T> {
+
+    private static final long serialVersionUID = 1L;
+
+    @SuppressWarnings("unchecked")
+    private static final ListPage EMPTY_LIST = new EmptyPagedList();
+
+    @SuppressWarnings("unchecked")
+    public static final <T> ListPage<T> emptyList() {
+        return (ListPage<T>) EMPTY_LIST;
+    }
+
+    private static class EmptyPagedList<T> extends AbstractList<T> implements
+            ListPage<T>, RandomAccess, Serializable {
+
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public int size() {
+            return 0;
+        }
+
+        @Override
+        public boolean contains(Object obj) {
+            return false;
+        }
+
+        @Override
+        public T get(int index) {
+            throw new IndexOutOfBoundsException(Integer.toString(index));
+        }
+
+        // singleton
+        private Object readResolve() {
+            return EMPTY_LIST;
+        }
+
+        public boolean getHasMoreItems() {
+            return false;
+        }
+
+        public int getNumItems() {
+            return 0;
+        }
+    }
+
+    protected boolean hasMoreItems;
+
+    protected int numItems = -1;
+
+    /**
+     * @see ArrayList#ArrayList()
+     */
+    public SimpleListPage() {
+        super();
+    }
+
+    /**
+     * @see ArrayList#ArrayList(int)
+     */
+    public SimpleListPage(int initialCapacity) {
+        super(initialCapacity);
+    }
+
+    /**
+     * @see ArrayList#ArrayList(Collection)
+     */
+    public SimpleListPage(Collection<? extends T> collection) {
+        super(collection);
+    }
+
+    public boolean getHasMoreItems() {
+        return hasMoreItems;
+    }
+
+    public int getNumItems() {
+        return numItems;
+    }
+
+    /**
+     * Sets whether the underlying collection has more items (skipped due to
+     * paging) after those included in the list.
+     */
+    public void setHasMoreItems(boolean hasMoreItems) {
+        this.hasMoreItems = hasMoreItems;
+    }
+
+    /**
+     * Sets the total number of items in the list (ignoring any paging).
+     */
+    public void setNumItems(int numItems) {
+        this.numItems = numItems;
+    }
+
+}

Propchange: incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleListPage.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleListPage.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: incubator/chemistry/trunk/chemistry/chemistry-jcr/src/main/java/org/apache/chemistry/jcr/JcrConnection.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-jcr/src/main/java/org/apache/chemistry/jcr/JcrConnection.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-jcr/src/main/java/org/apache/chemistry/jcr/JcrConnection.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-jcr/src/main/java/org/apache/chemistry/jcr/JcrConnection.java Fri Nov 20 13:45:27 2009
@@ -21,7 +21,6 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -41,8 +40,10 @@
 import org.apache.chemistry.ContentStream;
 import org.apache.chemistry.Document;
 import org.apache.chemistry.Folder;
+import org.apache.chemistry.ListPage;
 import org.apache.chemistry.ObjectEntry;
 import org.apache.chemistry.ObjectId;
+import org.apache.chemistry.Paging;
 import org.apache.chemistry.Policy;
 import org.apache.chemistry.Relationship;
 import org.apache.chemistry.RelationshipDirection;
@@ -51,6 +52,7 @@
 import org.apache.chemistry.SPI;
 import org.apache.chemistry.Unfiling;
 import org.apache.chemistry.VersioningState;
+import org.apache.chemistry.impl.simple.SimpleListPage;
 import org.apache.chemistry.impl.simple.SimpleObjectId;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -134,9 +136,8 @@
 
     public Collection<CMISObject> query(String statement,
             boolean searchAllVersions) {
-        boolean[] hasMoreItems = new boolean[1];
-        Collection<ObjectEntry> entries = query(statement, searchAllVersions,
-                false, false, false, Integer.MAX_VALUE, 0, hasMoreItems);
+        ListPage<ObjectEntry> entries = query(statement, searchAllVersions,
+                false, false, false, new Paging(Integer.MAX_VALUE, 0));
         List<CMISObject> objects = new ArrayList<CMISObject>(entries.size());
         for (ObjectEntry entry : entries) {
             // cast entries, they are all JcrFolder or JcrDocument
@@ -257,24 +258,18 @@
         throw new UnsupportedOperationException();
     }
 
-    public Collection<ObjectEntry> getCheckedOutDocuments(ObjectId folderId,
+    public ListPage<ObjectEntry> getCheckedOutDocuments(ObjectId folderId,
             String filter, boolean includeAllowableActions,
-            boolean includeRelationships, int maxItems, int skipCount,
-            boolean[] hasMoreItems) {
+            boolean includeRelationships, Paging paging) {
         // TODO Auto-generated method stub
         throw new UnsupportedOperationException();
     }
 
-    public List<ObjectEntry> getChildren(ObjectId folderId, String filter,
+    public ListPage<ObjectEntry> getChildren(ObjectId folderId, String filter,
             boolean includeAllowableActions, boolean includeRelationships,
-            boolean includeRenditions, int maxItems, int skipCount,
-            String orderBy, boolean[] hasMoreItems) {
+            boolean includeRenditions, String orderBy, Paging paging) {
 
         try {
-            if (maxItems == 0) {
-                maxItems = Integer.MAX_VALUE;
-            }
-
             Node node = session.getRootNode();
             String relPath = JcrObjectEntry.getPath(folderId.getId()).substring(
                     1);
@@ -287,12 +282,13 @@
             } else {
                 iter = node.getNodes(filter);
             }
-            /* Problem with skipCount == 0, when there are no more elements */
-            if (iter.hasNext()) {
-                iter.skip(skipCount);
+            if (iter.hasNext() && paging != null) {
+                iter.skip(paging.skipCount);
             }
 
-            List<ObjectEntry> result = new ArrayList<ObjectEntry>();
+            int maxItems = paging != null && paging.maxItems != 0 ? paging.maxItems
+                    : Integer.MAX_VALUE;
+            SimpleListPage<ObjectEntry> result = new SimpleListPage<ObjectEntry>();
             while (result.size() < maxItems && iter.hasNext()) {
                 Node child = iter.nextNode();
                 if (child.isNodeType(JcrConstants.NT_FOLDER)) {
@@ -301,7 +297,8 @@
                     result.add(new JcrDocument(child));
                 }
             }
-            hasMoreItems[0] = iter.hasNext();
+            result.setHasMoreItems(iter.hasNext());
+            result.setNumItems((int) iter.getSize());
             return result;
 
         } catch (RepositoryException e) {
@@ -413,18 +410,16 @@
         throw new UnsupportedOperationException();
     }
 
-    public List<ObjectEntry> getRelationships(ObjectId objectId,
+    public ListPage<ObjectEntry> getRelationships(ObjectId objectId,
             RelationshipDirection direction, String typeId,
             boolean includeSubRelationshipTypes, String filter,
-            String includeAllowableActions, int maxItems, int skipCount,
-            boolean[] hasMoreItems) {
-
-        return Collections.emptyList();
+            String includeAllowableActions, Paging paging) {
+        return SimpleListPage.emptyList();
     }
 
-    public List<Rendition> getRenditions(ObjectId object, String filter,
-            int maxItems, int skipCount) {
-        return Collections.emptyList();
+    public ListPage<Rendition> getRenditions(ObjectId object, String filter,
+            Paging paging) {
+        return SimpleListPage.emptyList();
     }
 
     public boolean hasContentStream(ObjectId document) {
@@ -438,19 +433,22 @@
         throw new UnsupportedOperationException();
     }
 
-    public Collection<ObjectEntry> query(String statement,
+    public ListPage<ObjectEntry> query(String statement,
             boolean searchAllVersions, boolean includeAllowableActions,
             boolean includeRelationships, boolean includeRenditions,
-            int maxItems, int skipCount, boolean[] hasMoreItems) {
+            Paging paging) {
 
         try {
             QueryManager qm = session.getWorkspace().getQueryManager();
             QueryResult qr = qm.createQuery(statement, Query.SQL).execute();
             NodeIterator iter = qr.getNodes();
-            iter.skip(skipCount);
-
-            List<ObjectEntry> result = new ArrayList<ObjectEntry>();
+            if (iter.hasNext() && paging != null) {
+                iter.skip(paging.skipCount);
+            }
 
+            int maxItems = paging != null && paging.maxItems != 0 ? paging.maxItems
+                    : Integer.MAX_VALUE;
+            SimpleListPage<ObjectEntry> result = new SimpleListPage<ObjectEntry>();
             while (result.size() < maxItems && iter.hasNext()) {
                 Node child = iter.nextNode();
                 if (child.isNodeType(JcrConstants.NT_FOLDER)) {
@@ -459,7 +457,8 @@
                     result.add(new JcrDocument(child));
                 }
             }
-            hasMoreItems[0] = iter.hasNext();
+            result.setHasMoreItems(iter.hasNext());
+            result.setNumItems((int) iter.getSize());
             return result;
 
         } catch (RepositoryException e) {
@@ -491,12 +490,11 @@
         throw new UnsupportedOperationException();
     }
 
-    public Iterator<ObjectEntry> getChangeLog(String changeLogToken,
-            boolean includeProperties, int maxItems, boolean[] hasMoreItems,
+    public ListPage<ObjectEntry> getChangeLog(String changeLogToken,
+            boolean includeProperties, Paging paging,
             String[] latestChangeLogToken) {
-        hasMoreItems[0] = false;
         latestChangeLogToken[0] = null;
-        return Collections.<ObjectEntry> emptyList().iterator();
+        return SimpleListPage.emptyList();
     }
 
     public List<ACE> getACL(ObjectId object, boolean onlyBasicPermissions,

Modified: incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java?rev=882549&r1=882548&r2=882549&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java Fri Nov 20 13:45:27 2009
@@ -42,8 +42,10 @@
 import org.apache.chemistry.ContentStream;
 import org.apache.chemistry.Document;
 import org.apache.chemistry.Folder;
+import org.apache.chemistry.ListPage;
 import org.apache.chemistry.ObjectEntry;
 import org.apache.chemistry.ObjectId;
+import org.apache.chemistry.Paging;
 import org.apache.chemistry.Property;
 import org.apache.chemistry.Repository;
 import org.apache.chemistry.RepositoryCapabilities;
@@ -219,31 +221,47 @@
     }
 
     public void testGetChildren() {
-        boolean[] hasMoreItems = new boolean[1];
         Folder root = conn.getRootFolder();
-        assertEquals(1, spi.getChildren(root, null, true, false, false, 20, 0,
-                null, hasMoreItems).size());
-        assertFalse(hasMoreItems[0]);
+        ListPage<ObjectEntry> page = spi.getChildren(root, null, true, false,
+                false, null, new Paging(20, 0));
+        assertEquals(1, page.size());
+        assertFalse(page.getHasMoreItems());
+        assertEquals(1, page.getNumItems());
+
         ObjectId folder1 = root.getChildren().get(0);
-        assertEquals(2, spi.getChildren(folder1, null, false, false, false, 20,
-                0, null, hasMoreItems).size());
-        assertFalse(hasMoreItems[0]);
-        assertEquals(1, spi.getChildren(folder1, null, false, false, false, 1,
-                0, null, hasMoreItems).size());
-        assertTrue(hasMoreItems[0]);
-        assertEquals(1, spi.getChildren(folder1, null, false, false, false, 1,
-                1, null, hasMoreItems).size());
-        assertFalse(hasMoreItems[0]);
-        List<ObjectEntry> temp = spi.getChildren(folder1, null, false, false,
-                false, 2, 0, null, hasMoreItems);
-        ObjectId folder2 = temp.get(0).getTypeId().equals("fold") ? temp.get(0)
-                : temp.get(1);
-        assertEquals(1, spi.getChildren(folder2, null, false, false, false, 1,
-                1, null, hasMoreItems).size());
-        assertTrue(hasMoreItems[0]);
-        assertEquals(2, spi.getChildren(folder2, null, false, false, false, 2,
-                0, null, hasMoreItems).size());
-        assertTrue(hasMoreItems[0]);
+        page = spi.getChildren(folder1, null, false, false, false, null,
+                new Paging(20, 0));
+        assertEquals(2, page.size());
+        assertFalse(page.getHasMoreItems());
+        assertEquals(2, page.getNumItems());
+
+        page = spi.getChildren(folder1, null, false, false, false, null,
+                new Paging(1, 0));
+        assertEquals(1, page.size());
+        assertTrue(page.getHasMoreItems());
+        assertEquals(2, page.getNumItems());
+
+        page = spi.getChildren(folder1, null, false, false, false, null,
+                new Paging(1, 1));
+        assertEquals(1, page.size());
+        assertFalse(page.getHasMoreItems());
+        assertEquals(2, page.getNumItems());
+
+        page = spi.getChildren(folder1, null, false, false, false, null,
+                new Paging(2, 0));
+        ObjectId folder2 = page.get(0).getTypeId().equals("fold") ? page.get(0)
+                : page.get(1);
+        page = spi.getChildren(folder2, null, false, false, false, null,
+                new Paging(1, 1));
+        assertEquals(1, page.size());
+        assertTrue(page.getHasMoreItems());
+        assertEquals(3, page.getNumItems());
+
+        page = spi.getChildren(folder2, null, false, false, false, null,
+                new Paging(2, 0));
+        assertEquals(2, page.size());
+        assertTrue(page.getHasMoreItems());
+        assertEquals(3, page.getNumItems());
     }
 
     public void testGetFolderTree() {



Mime
View raw message