You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by fm...@apache.org on 2013/09/17 15:35:53 UTC

svn commit: r1524038 - in /chemistry/opencmis/trunk: chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/ chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/c...

Author: fmui
Date: Tue Sep 17 13:35:52 2013
New Revision: 1524038

URL: http://svn.apache.org/r1524038
Log:
CMIS-722: added a change log iterator

Added:
    chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/spi/ExtendedHolder.java   (with props)
Modified:
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/Session.java
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/DiscoveryServiceImpl.java
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/SessionImpl.java
    chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/spi/Holder.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/AtomFeed.java
    chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-tck/src/main/java/org/apache/chemistry/opencmis/tck/tests/query/ContentChangesSmokeTest.java

Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/Session.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/Session.java?rev=1524038&r1=1524037&r2=1524038&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/Session.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/Session.java Tue Sep 17 13:35:52 2013
@@ -95,7 +95,7 @@ public interface Session extends Seriali
      * 
      * @param context
      *            the <code>OperationContext</code> to be used for the session;
-     *            if <code>null</code>, a default context is used
+     *            if {@code null}, a default context is used
      */
     void setDefaultContext(OperationContext context);
 
@@ -387,7 +387,7 @@ public interface Session extends Seriali
      * Returns the content changes.
      * 
      * @param changeLogToken
-     *            the change log token to start from or <code>null</code>
+     *            the change log token to start from or {@code null}
      * @param includeProperties
      *            indicates if changed properties should be included in the
      *            result
@@ -402,7 +402,7 @@ public interface Session extends Seriali
      * Returns the content changes.
      * 
      * @param changeLogToken
-     *            the change log token to start from or <code>null</code>
+     *            the change log token to start from or {@code null}
      * @param includeProperties
      *            indicates if changed properties should be included in the
      *            result
@@ -416,6 +416,37 @@ public interface Session extends Seriali
     ChangeEvents getContentChanges(String changeLogToken, boolean includeProperties, long maxNumItems,
             OperationContext context);
 
+    /**
+     * Returns an iterator of content changes, starting from the given change
+     * log token to the latest entry in the change log.
+     * 
+     * @param changeLogToken
+     *            the change log token to start from or {@code null}
+     * @param includeProperties
+     *            indicates if changed properties should be included in the
+     *            result
+     * 
+     * @cmis 1.0
+     */
+    public ItemIterable<ChangeEvent> getContentChanges(String changeLogToken, boolean includeProperties);
+
+    /**
+     * Returns an iterator of content changes, starting from the given change
+     * log token to the latest entry in the change log.
+     * 
+     * @param changeLogToken
+     *            the change log token to start from or {@code null}
+     * @param includeProperties
+     *            indicates if changed properties should be included in the
+     *            result
+     * @param context
+     *            the OperationContext
+     * 
+     * @cmis 1.0
+     */
+    public ItemIterable<ChangeEvent> getContentChanges(final String changeLogToken, final boolean includeProperties,
+            OperationContext context);
+
     // create
 
     /**
@@ -609,8 +640,8 @@ public interface Session extends Seriali
      * 
      * @param docId
      *            the id of the document
-     * @return the content stream or <code>null</code> if the document has no
-     *         content stream
+     * @return the content stream or {@code null} if the document has no content
+     *         stream
      * 
      * @cmis 1.0
      */
@@ -624,14 +655,14 @@ public interface Session extends Seriali
      * @param streamId
      *            the stream id
      * @param offset
-     *            the offset of the stream or <code>null</code> to read the
-     *            stream from the beginning
+     *            the offset of the stream or {@code null} to read the stream
+     *            from the beginning
      * @param length
-     *            the maximum length of the stream or <code>null</code> to read
-     *            to the end of the stream
+     *            the maximum length of the stream or {@code null} to read to
+     *            the end of the stream
      * 
-     * @return the content stream or <code>null</code> if the document has no
-     *         content stream
+     * @return the content stream or {@code null} if the document has no content
+     *         stream
      * 
      * @cmis 1.0
      */
@@ -662,14 +693,14 @@ public interface Session extends Seriali
      * @param objectId
      *            the id the object
      * @param addAces
-     *            list of ACEs to be added or <code>null</code> if no ACEs
-     *            should be added
+     *            list of ACEs to be added or {@code null} if no ACEs should be
+     *            added
      * @param removeAces
-     *            list of ACEs to be removed or <code>null</code> if no ACEs
-     *            should be removed
+     *            list of ACEs to be removed or {@code null} if no ACEs should
+     *            be removed
      * @param aclPropagation
      *            value that defines the propagation of the ACE changes;
-     *            <code>null</code> is equal to
+     *            {@code null} is equal to
      *            {@link AclPropagation#REPOSITORYDETERMINED}
      * 
      * @return the new ACL of the object

Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/DiscoveryServiceImpl.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/DiscoveryServiceImpl.java?rev=1524038&r1=1524037&r2=1524038&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/DiscoveryServiceImpl.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/atompub/DiscoveryServiceImpl.java Tue Sep 17 13:35:52 2013
@@ -44,6 +44,7 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectListImpl;
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.QueryTypeImpl;
 import org.apache.chemistry.opencmis.commons.spi.DiscoveryService;
+import org.apache.chemistry.opencmis.commons.spi.ExtendedHolder;
 import org.apache.chemistry.opencmis.commons.spi.Holder;
 
 /**
@@ -63,29 +64,48 @@ public class DiscoveryServiceImpl extend
         ObjectListImpl result = new ObjectListImpl();
 
         // find the link
-        String link = loadRepositoryLink(repositoryId, Constants.REP_REL_CHANGES);
+        String link = null;
+        UrlBuilder url = null;
 
+        // if the application doesn't know the change log token but the link to
+        // the next Atom feed
+        if (changeLogToken instanceof ExtendedHolder && changeLogToken.getValue() == null) {
+            link = (String) ((ExtendedHolder<String>) changeLogToken).getExtraValue(Constants.REP_REL_CHANGES);
+            if (link != null) {
+                url = new UrlBuilder(link);
+            }
+        }
+
+        // if the application didn't provide a link to next Atom feed
         if (link == null) {
-            throw new CmisObjectNotFoundException("Unknown repository or content changes not supported!");
+            link = loadRepositoryLink(repositoryId, Constants.REP_REL_CHANGES);
+            if (link != null) {
+                url = new UrlBuilder(link);
+                url.addParameter(Constants.PARAM_CHANGE_LOG_TOKEN,
+                        (changeLogToken == null ? null : changeLogToken.getValue()));
+                url.addParameter(Constants.PARAM_PROPERTIES, includeProperties);
+                url.addParameter(Constants.PARAM_FILTER, filter);
+                url.addParameter(Constants.PARAM_POLICY_IDS, includePolicyIds);
+                url.addParameter(Constants.PARAM_ACL, includeACL);
+                url.addParameter(Constants.PARAM_MAX_ITEMS, maxItems);
+            }
         }
 
-        UrlBuilder url = new UrlBuilder(link);
-        url.addParameter(Constants.PARAM_CHANGE_LOG_TOKEN, (changeLogToken == null ? null : changeLogToken.getValue()));
-        url.addParameter(Constants.PARAM_PROPERTIES, includeProperties);
-        url.addParameter(Constants.PARAM_FILTER, filter);
-        url.addParameter(Constants.PARAM_POLICY_IDS, includePolicyIds);
-        url.addParameter(Constants.PARAM_ACL, includeACL);
-        url.addParameter(Constants.PARAM_MAX_ITEMS, maxItems);
+        if (link == null) {
+            throw new CmisObjectNotFoundException("Unknown repository or content changes not supported!");
+        }
 
         // read and parse
         Response resp = read(url);
         AtomFeed feed = parse(resp.getStream(), AtomFeed.class);
 
         // handle top level
+        String nextLink = null;
         for (AtomElement element : feed.getElements()) {
             if (element.getObject() instanceof AtomLink) {
                 if (isNextLink(element)) {
                     result.setHasMoreItems(Boolean.TRUE);
+                    nextLink = ((AtomLink) element.getObject()).getHref();
                 }
             } else if (isInt(NAME_NUM_ITEMS, element)) {
                 result.setNumItems((BigInteger) element.getObject());
@@ -115,6 +135,11 @@ public class DiscoveryServiceImpl extend
         if (changeLogToken != null) {
             // the AtomPub binding cannot return a new change log token
             changeLogToken.setValue(null);
+
+            // but we can provide the link to the next Atom feed
+            if (changeLogToken instanceof ExtendedHolder && nextLink != null) {
+                ((ExtendedHolder<String>) changeLogToken).setExtraValue(Constants.REP_REL_CHANGES, nextLink);
+            }
         }
 
         return result;

Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/SessionImpl.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/SessionImpl.java?rev=1524038&r1=1524037&r2=1524038&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/SessionImpl.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/SessionImpl.java Tue Sep 17 13:35:52 2013
@@ -23,12 +23,14 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
+import org.apache.chemistry.opencmis.client.api.ChangeEvent;
 import org.apache.chemistry.opencmis.client.api.ChangeEvents;
 import org.apache.chemistry.opencmis.client.api.CmisObject;
 import org.apache.chemistry.opencmis.client.api.Document;
@@ -74,12 +76,14 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
 import org.apache.chemistry.opencmis.commons.impl.ClassLoaderUtil;
+import org.apache.chemistry.opencmis.commons.impl.Constants;
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.BulkUpdateObjectIdAndChangeTokenImpl;
 import org.apache.chemistry.opencmis.commons.spi.AclService;
 import org.apache.chemistry.opencmis.commons.spi.AuthenticationProvider;
 import org.apache.chemistry.opencmis.commons.spi.CmisBinding;
 import org.apache.chemistry.opencmis.commons.spi.DiscoveryService;
 import org.apache.chemistry.opencmis.commons.spi.ExtendedAclService;
+import org.apache.chemistry.opencmis.commons.spi.ExtendedHolder;
 import org.apache.chemistry.opencmis.commons.spi.Holder;
 import org.apache.chemistry.opencmis.commons.spi.NavigationService;
 import org.apache.chemistry.opencmis.commons.spi.RelationshipService;
@@ -320,18 +324,84 @@ public class SessionImpl implements Sess
             throw new IllegalArgumentException("Operation context must be set!");
         }
 
+        Holder<String> changeLogTokenHolder = new Holder<String>(changeLogToken);
+        ObjectList objectList = null;
+
         lock.readLock().lock();
         try {
-            Holder<String> changeLogTokenHolder = new Holder<String>(changeLogToken);
-
-            ObjectList objectList = getBinding().getDiscoveryService().getContentChanges(getRepositoryInfo().getId(),
+            objectList = getBinding().getDiscoveryService().getContentChanges(getRepositoryInfo().getId(),
                     changeLogTokenHolder, includeProperties, context.getFilterString(), context.isIncludePolicies(),
                     context.isIncludeAcls(), BigInteger.valueOf(maxNumItems), null);
-
-            return objectFactory.convertChangeEvents(changeLogTokenHolder.getValue(), objectList);
         } finally {
             lock.readLock().unlock();
         }
+
+        return objectFactory.convertChangeEvents(changeLogTokenHolder.getValue(), objectList);
+    }
+
+    public ItemIterable<ChangeEvent> getContentChanges(String changeLogToken, final boolean includeProperties) {
+        return getContentChanges(changeLogToken, includeProperties, getDefaultContext());
+    }
+
+    public ItemIterable<ChangeEvent> getContentChanges(final String changeLogToken, final boolean includeProperties,
+            OperationContext context) {
+        if (context == null) {
+            throw new IllegalArgumentException("Operation context must be set!");
+        }
+
+        final DiscoveryService discoveryService = getBinding().getDiscoveryService();
+        final ObjectFactory of = this.getObjectFactory();
+        final OperationContext ctxt = new OperationContextImpl(context);
+
+        return new CollectionIterable<ChangeEvent>(new AbstractPageFetcher<ChangeEvent>(ctxt.getMaxItemsPerPage()) {
+
+            private String token = changeLogToken;
+            private String nextLink = null;
+            private boolean firstPage = true;
+
+            @Override
+            protected AbstractPageFetcher.Page<ChangeEvent> fetchPage(long skipCount) {
+                assert firstPage || token != null ? (nextLink == null) : true;
+
+                // fetch the data
+                ExtendedHolder<String> changeLogTokenHolder = new ExtendedHolder<String>(token);
+                if (nextLink != null) {
+                    changeLogTokenHolder.setExtraValue(Constants.REP_REL_CHANGES, nextLink);
+                }
+
+                ObjectList objectList = discoveryService.getContentChanges(getRepositoryInfo().getId(),
+                        changeLogTokenHolder, includeProperties, ctxt.getFilterString(), ctxt.isIncludePolicies(),
+                        ctxt.isIncludeAcls(), BigInteger.valueOf(this.maxNumItems), null);
+
+                // convert type definitions
+                LinkedList<ChangeEvent> page = new LinkedList<ChangeEvent>();
+                for (ObjectData objectData : objectList.getObjects()) {
+                    page.add(of.convertChangeEvent(objectData));
+                }
+
+                if (!firstPage && nextLink == null) {
+                    // the web services and the browser binding repeat the last
+                    // entry of the previous page -> remove the first entry
+                    page.removeFirst();
+                }
+                firstPage = false;
+
+                if (changeLogTokenHolder.getValue() != null) {
+                    // the web services and the browser binding
+                    // return a new token
+                    token = changeLogTokenHolder.getValue();
+                } else {
+                    // the atompub binding does not return a new token,
+                    // but might return a link to the next Atom feed
+                    token = null;
+                    nextLink = (String) changeLogTokenHolder.getExtraValue(Constants.REP_REL_CHANGES);
+                }
+
+                return new AbstractPageFetcher.Page<ChangeEvent>(page, objectList.getNumItems(),
+                        objectList.hasMoreItems()) {
+                };
+            }
+        });
     }
 
     public OperationContext getDefaultContext() {
@@ -460,7 +530,7 @@ public class SessionImpl implements Sess
     }
 
     public void removeObjectFromCache(ObjectId objectId) {
-        if ((objectId == null) || (objectId.getId() == null)) {
+        if (objectId == null || objectId.getId() == null) {
             return;
         }
 
@@ -474,7 +544,7 @@ public class SessionImpl implements Sess
     public RepositoryInfo getRepositoryInfo() {
         lock.readLock().lock();
         try {
-            return this.repositoryInfo;
+            return repositoryInfo;
         } finally {
             lock.readLock().unlock();
         }
@@ -719,7 +789,7 @@ public class SessionImpl implements Sess
     public CmisBinding getBinding() {
         lock.readLock().lock();
         try {
-            return this.binding;
+            return binding;
         } finally {
             lock.readLock().unlock();
         }
@@ -728,7 +798,7 @@ public class SessionImpl implements Sess
     public Cache getCache() {
         lock.readLock().lock();
         try {
-            return this.cache;
+            return cache;
         } finally {
             lock.readLock().unlock();
         }

Added: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/spi/ExtendedHolder.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/spi/ExtendedHolder.java?rev=1524038&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/spi/ExtendedHolder.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/spi/ExtendedHolder.java Tue Sep 17 13:35:52 2013
@@ -0,0 +1,55 @@
+package org.apache.chemistry.opencmis.commons.spi;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Holder for IN/OUT parameters that can hold extra values.
+ */
+public class ExtendedHolder<T> extends Holder<T> {
+
+    private Map<String, Object> extraValues = new HashMap<String, Object>();
+
+    /**
+     * Constructs a holder with a {@code null} value.
+     */
+    public ExtendedHolder() {
+        super();
+    }
+
+    /**
+     * Constructs a holder with the given value.
+     */
+    public ExtendedHolder(T value) {
+        super(value);
+    }
+
+    /**
+     * Sets an extra value.
+     * 
+     * @param name
+     *            the name of the value
+     * @param value
+     *            the value
+     */
+    public void setExtraValue(String name, Object value) {
+        extraValues.put(name, value);
+    }
+
+    /**
+     * Gets an extra value,
+     * 
+     * @param name
+     *            the name of the value
+     * @return the value or {@code null} if a value with the given name doesn't
+     *         exist
+     */
+    public Object getExtraValue(String name) {
+        return extraValues.get(name);
+    }
+
+    @Override
+    public String toString() {
+        return "ExtendedHolder(" + getValue() + ", " + extraValues.toString() + ")";
+    }
+}

Propchange: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/spi/ExtendedHolder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/spi/Holder.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/spi/Holder.java?rev=1524038&r1=1524037&r2=1524038&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/spi/Holder.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/spi/Holder.java Tue Sep 17 13:35:52 2013
@@ -21,27 +21,44 @@ package org.apache.chemistry.opencmis.co
 /**
  * Holder for IN/OUT parameters.
  */
-public final class Holder<T> {
+public class Holder<T> {
 
-    private T fValue;
+    private T value;
 
+    /**
+     * Constructs a holder with a {@code null} value.
+     */
     public Holder() {
     }
 
+    /**
+     * Constructs a holder with the given value.
+     */
     public Holder(T value) {
-        fValue = value;
+        this.value = value;
     }
 
+    /**
+     * Returns the value.
+     * 
+     * @return the value of the holder
+     */
     public T getValue() {
-        return fValue;
+        return value;
     }
 
+    /**
+     * Sets a new value of the holder.
+     * 
+     * @param value
+     *            the new value
+     */
     public void setValue(T value) {
-        fValue = value;
+        this.value = value;
     }
 
     @Override
     public String toString() {
-        return "Holder(" + fValue + ")";
+        return "Holder(" + value + ")";
     }
 }

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/AtomFeed.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/AtomFeed.java?rev=1524038&r1=1524037&r2=1524038&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/AtomFeed.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/AtomFeed.java Tue Sep 17 13:35:52 2013
@@ -150,7 +150,7 @@ public class AtomFeed extends AtomDocume
         }
 
         // if has more -> add "next" link
-        if ((hasMoreItems != null) && hasMoreItems.booleanValue()) {
+        if (Boolean.TRUE.equals(hasMoreItems)) {
             // next link
             UrlBuilder nextLink = new UrlBuilder(pagingUrl);
             nextLink.addParameter(Constants.PARAM_SKIP_COUNT, skipCount.add(maxItems));

Modified: chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-tck/src/main/java/org/apache/chemistry/opencmis/tck/tests/query/ContentChangesSmokeTest.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-tck/src/main/java/org/apache/chemistry/opencmis/tck/tests/query/ContentChangesSmokeTest.java?rev=1524038&r1=1524037&r2=1524038&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-tck/src/main/java/org/apache/chemistry/opencmis/tck/tests/query/ContentChangesSmokeTest.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-tck/src/main/java/org/apache/chemistry/opencmis/tck/tests/query/ContentChangesSmokeTest.java Tue Sep 17 13:35:52 2013
@@ -52,6 +52,7 @@ public class ContentChangesSmokeTest ext
         CmisTestResult f;
 
         if (supportsContentChanges(session)) {
+            // get a page of 100 entries
             ChangeEvents events = session.getContentChanges(null, true, 1000, SELECT_ALL_NO_CACHE_OC);
 
             f = createResult(FAILURE, "Change events are null!");
@@ -63,40 +64,21 @@ public class ContentChangesSmokeTest ext
                     // the AtompPub binding does not return a change log token
                     f = createResult(FAILURE, "Change log token is null!");
                     addResult(assertNotNull(events.getLatestChangeLogToken(), null, f));
+                } else {
+                    // this would be an OpenCMIS bug, not a server issue
+                    f = createResult(FAILURE, "Change log is not null although the AtomPub binding cannot return one!");
+                    addResult(assertNull(events.getLatestChangeLogToken(), null, f));
                 }
 
                 for (ChangeEvent event : events.getChangeEvents()) {
-                    f = createResult(FAILURE, "Object Id is not set!");
-                    addResult(assertStringNotEmpty(event.getObjectId(), null, f));
-
-                    f = createResult(FAILURE, "Change Type is not set! Id: " + event.getObjectId());
-                    addResult(assertNotNull(event.getChangeType(), null, f));
-
-                    f = createResult(FAILURE, "Change Time is not set! Id: " + event.getObjectId());
-                    addResult(assertNotNull(event.getChangeTime(), null, f));
-
-                    if (event.getObjectId() != null) {
-                        if (event.getChangeType() == ChangeType.DELETED) {
-                            try {
-                                session.getObject(event.getObjectId(), SELECT_ALL_NO_CACHE_OC);
-                                addResult(createResult(FAILURE,
-                                        "Change event indicates that an object has been deleted but it still exists. Id: "
-                                                + event.getObjectId()));
-                            } catch (CmisObjectNotFoundException e) {
-                                // expected
-                            }
-                        } else {
-                            try {
-                                CmisObject object = session.getObject(event.getObjectId(), SELECT_ALL_NO_CACHE_OC);
-                                addResult(checkObject(session, object, getAllProperties(object), "Object check. Id: "
-                                        + event.getObjectId()));
-                            } catch (CmisObjectNotFoundException e) {
-                                // object might have been deleted later
-                            }
-                        }
-                    }
+                    checkChangeEvent(session, event);
                 }
             }
+
+            // get all entries
+            for (ChangeEvent event : session.getContentChanges(null, true, SELECT_ALL_NO_CACHE_OC)) {
+                checkChangeEvent(session, event);
+            }
         } else {
             addResult(createResult(SKIPPED, "Content Changes not supported. Test Skipped!"));
         }
@@ -111,4 +93,39 @@ public class ContentChangesSmokeTest ext
 
         return repository.getCapabilities().getChangesCapability() != CapabilityChanges.NONE;
     }
+
+    protected void checkChangeEvent(Session session, ChangeEvent event) {
+        CmisTestResult f;
+
+        f = createResult(FAILURE, "Object Id is not set!");
+        addResult(assertStringNotEmpty(event.getObjectId(), null, f));
+
+        f = createResult(FAILURE, "Change Type is not set! Id: " + event.getObjectId());
+        addResult(assertNotNull(event.getChangeType(), null, f));
+
+        f = createResult(FAILURE, "Change Time is not set! Id: " + event.getObjectId());
+        addResult(assertNotNull(event.getChangeTime(), null, f));
+
+        if (event.getObjectId() != null) {
+            if (event.getChangeType() == ChangeType.DELETED) {
+                try {
+                    session.getObject(event.getObjectId(), SELECT_ALL_NO_CACHE_OC);
+                    addResult(createResult(
+                            FAILURE,
+                            "Change event indicates that an object has been deleted but it still exists. Id: "
+                                    + event.getObjectId()));
+                } catch (CmisObjectNotFoundException e) {
+                    // expected
+                }
+            } else {
+                try {
+                    CmisObject object = session.getObject(event.getObjectId(), SELECT_ALL_NO_CACHE_OC);
+                    addResult(checkObject(session, object, getAllProperties(object),
+                            "Object check. Id: " + event.getObjectId()));
+                } catch (CmisObjectNotFoundException e) {
+                    // object might have been deleted later
+                }
+            }
+        }
+    }
 }