This project has retired. For details please refer to its Attic page.
NavigationService xref

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.chemistry.opencmis.server.impl.atompub;
20  
21  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_ACL;
22  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_ALLOWABLEACIONS;
23  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_CHECKEDOUT;
24  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_CHILDREN;
25  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_CONTENT;
26  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_DESCENDANTS;
27  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_ENTRY;
28  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_FOLDERTREE;
29  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_PARENTS;
30  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_POLICIES;
31  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_RELATIONSHIPS;
32  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.RESOURCE_TYPE;
33  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.compileBaseUrl;
34  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.compileUrl;
35  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.compileUrlBuilder;
36  import static org.apache.chemistry.opencmis.server.impl.atompub.AtomPubUtils.writeObjectEntry;
37  import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getBigIntegerParameter;
38  import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getBooleanParameter;
39  import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getEnumParameter;
40  import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getStringParameter;
41  
42  import java.math.BigInteger;
43  import java.util.GregorianCalendar;
44  import java.util.List;
45  
46  import javax.servlet.http.HttpServletRequest;
47  import javax.servlet.http.HttpServletResponse;
48  
49  import org.apache.chemistry.opencmis.commons.data.ObjectData;
50  import org.apache.chemistry.opencmis.commons.data.ObjectInFolderContainer;
51  import org.apache.chemistry.opencmis.commons.data.ObjectInFolderData;
52  import org.apache.chemistry.opencmis.commons.data.ObjectInFolderList;
53  import org.apache.chemistry.opencmis.commons.data.ObjectList;
54  import org.apache.chemistry.opencmis.commons.data.ObjectParentData;
55  import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
56  import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
57  import org.apache.chemistry.opencmis.commons.impl.Constants;
58  import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
59  import org.apache.chemistry.opencmis.commons.impl.server.ObjectInfoImpl;
60  import org.apache.chemistry.opencmis.commons.server.CallContext;
61  import org.apache.chemistry.opencmis.commons.server.CmisService;
62  import org.apache.chemistry.opencmis.commons.server.ObjectInfo;
63  import org.apache.chemistry.opencmis.commons.server.RenditionInfo;
64  
65  /**
66   * Navigation Service operations.
67   */
68  public final class NavigationService {
69  
70      private NavigationService() {
71      }
72  
73      /**
74       * Children Collection GET.
75       */
76      public static void getChildren(CallContext context, CmisService service, String repositoryId,
77              HttpServletRequest request, HttpServletResponse response) throws Exception {
78          // get parameters
79          String folderId = getStringParameter(request, Constants.PARAM_ID);
80          String filter = getStringParameter(request, Constants.PARAM_FILTER);
81          String orderBy = getStringParameter(request, Constants.PARAM_ORDER_BY);
82          Boolean includeAllowableActions = getBooleanParameter(request, Constants.PARAM_ALLOWABLE_ACTIONS);
83          IncludeRelationships includeRelationships = getEnumParameter(request, Constants.PARAM_RELATIONSHIPS,
84                  IncludeRelationships.class);
85          String renditionFilter = getStringParameter(request, Constants.PARAM_RENDITION_FILTER);
86          Boolean includePathSegment = getBooleanParameter(request, Constants.PARAM_PATH_SEGMENT);
87          BigInteger maxItems = getBigIntegerParameter(request, Constants.PARAM_MAX_ITEMS);
88          BigInteger skipCount = getBigIntegerParameter(request, Constants.PARAM_SKIP_COUNT);
89  
90          // execute
91          ObjectInFolderList children = service.getChildren(repositoryId, folderId, filter, orderBy,
92                  includeAllowableActions, includeRelationships, renditionFilter, includePathSegment, maxItems,
93                  skipCount, null);
94  
95          if (children == null) {
96              throw new CmisRuntimeException("Children are null!");
97          }
98  
99          ObjectInfo folderInfo = service.getObjectInfo(repositoryId, folderId);
100         if (folderInfo == null) {
101             throw new CmisRuntimeException("Folder Object Info is missing!");
102         }
103 
104         // set headers
105         response.setStatus(HttpServletResponse.SC_OK);
106         response.setContentType(Constants.MEDIATYPE_FEED);
107 
108         // write XML
109         AtomFeed feed = new AtomFeed();
110         feed.startDocument(response.getOutputStream());
111         feed.startFeed(true);
112 
113         // write basic Atom feed elements
114         feed.writeFeedElements(folderInfo.getId(), folderInfo.getCreatedBy(), folderInfo.getName(),
115                 folderInfo.getLastModificationDate(), null, children.getNumItems());
116 
117         // write links
118         UrlBuilder baseUrl = compileBaseUrl(request, repositoryId);
119 
120         feed.writeServiceLink(baseUrl.toString(), repositoryId);
121 
122         feed.writeSelfLink(compileUrl(baseUrl, RESOURCE_CHILDREN, folderInfo.getId()), null);
123 
124         feed.writeDescribedByLink(compileUrl(baseUrl, RESOURCE_TYPE, folderInfo.getTypeId()));
125 
126         feed.writeAllowableActionsLink(compileUrl(baseUrl, RESOURCE_ALLOWABLEACIONS, folderInfo.getId()));
127 
128         feed.writeDownLink(compileUrl(baseUrl, RESOURCE_CHILDREN, folderInfo.getId()), Constants.MEDIATYPE_FEED);
129 
130         if (folderInfo.supportsDescendants()) {
131             feed.writeDownLink(compileUrl(baseUrl, RESOURCE_DESCENDANTS, folderInfo.getId()),
132                     Constants.MEDIATYPE_DESCENDANTS);
133         }
134 
135         if (folderInfo.supportsFolderTree()) {
136             feed.writeFolderTreeLink(compileUrl(baseUrl, RESOURCE_FOLDERTREE, folderInfo.getId()));
137         }
138 
139         if (folderInfo.hasParent()) {
140             feed.writeUpLink(compileUrl(baseUrl, RESOURCE_PARENTS, folderInfo.getId()), Constants.MEDIATYPE_FEED);
141         }
142 
143         if (folderInfo.getRenditionInfos() != null) {
144             for (RenditionInfo ri : folderInfo.getRenditionInfos()) {
145                 feed.writeAlternateLink(compileUrl(baseUrl, RESOURCE_CONTENT, ri.getId()), ri.getContenType(),
146                         ri.getKind(), ri.getTitle(), ri.getLength());
147             }
148         }
149 
150         if (folderInfo.hasAcl()) {
151             feed.writeAclLink(compileUrl(baseUrl, RESOURCE_ACL, folderInfo.getId()));
152         }
153 
154         if (folderInfo.supportsPolicies()) {
155             feed.writeAclLink(compileUrl(baseUrl, RESOURCE_POLICIES, folderInfo.getId()));
156         }
157 
158         if (folderInfo.supportsRelationships()) {
159             feed.writeRelationshipsLink(compileUrl(baseUrl, RESOURCE_RELATIONSHIPS, folderInfo.getId()));
160         }
161 
162         UrlBuilder pagingUrl = new UrlBuilder(compileUrlBuilder(baseUrl, RESOURCE_CHILDREN, folderInfo.getId()));
163         pagingUrl.addParameter(Constants.PARAM_FILTER, filter);
164         pagingUrl.addParameter(Constants.PARAM_ORDER_BY, orderBy);
165         pagingUrl.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
166         pagingUrl.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
167         pagingUrl.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
168         pagingUrl.addParameter(Constants.PARAM_PATH_SEGMENT, includePathSegment);
169         feed.writePagingLinks(pagingUrl, maxItems, skipCount, children.getNumItems(), children.hasMoreItems(),
170                 AtomPubUtils.PAGE_SIZE);
171 
172         // write collection
173         feed.writeCollection(compileUrl(baseUrl, RESOURCE_CHILDREN, folderInfo.getId()), null, "Folder collection",
174                 Constants.MEDIATYPE_CMISATOM);
175 
176         // write entries
177         if (children.getObjects() != null) {
178             AtomEntry entry = new AtomEntry(feed.getWriter());
179             for (ObjectInFolderData object : children.getObjects()) {
180                 if ((object == null) || (object.getObject() == null)) {
181                     continue;
182                 }
183                 writeObjectEntry(service, entry, object.getObject(), null, repositoryId, object.getPathSegment(), null,
184                         baseUrl, false);
185             }
186         }
187 
188         // we are done
189         feed.endFeed();
190         feed.endDocument();
191     }
192 
193     /**
194      * Descendants feed GET.
195      */
196     public static void getDescendants(CallContext context, CmisService service, String repositoryId,
197             HttpServletRequest request, HttpServletResponse response) throws Exception {
198         // get parameters
199         String folderId = getStringParameter(request, Constants.PARAM_ID);
200         BigInteger depth = getBigIntegerParameter(request, Constants.PARAM_DEPTH);
201         String filter = getStringParameter(request, Constants.PARAM_FILTER);
202         Boolean includeAllowableActions = getBooleanParameter(request, Constants.PARAM_ALLOWABLE_ACTIONS);
203         IncludeRelationships includeRelationships = getEnumParameter(request, Constants.PARAM_RELATIONSHIPS,
204                 IncludeRelationships.class);
205         String renditionFilter = getStringParameter(request, Constants.PARAM_RENDITION_FILTER);
206         Boolean includePathSegment = getBooleanParameter(request, Constants.PARAM_PATH_SEGMENT);
207 
208         // execute
209         List<ObjectInFolderContainer> descendants = service.getDescendants(repositoryId, folderId, depth, filter,
210                 includeAllowableActions, includeRelationships, renditionFilter, includePathSegment, null);
211 
212         if (descendants == null) {
213             throw new CmisRuntimeException("Descendants are null!");
214         }
215 
216         ObjectInfo folderInfo = service.getObjectInfo(repositoryId, folderId);
217         if (folderInfo == null) {
218             throw new CmisRuntimeException("Folder Object Info is missing!");
219         }
220 
221         // set headers
222         response.setStatus(HttpServletResponse.SC_OK);
223         response.setContentType(Constants.MEDIATYPE_FEED);
224 
225         // write XML
226         AtomFeed feed = new AtomFeed();
227         feed.startDocument(response.getOutputStream());
228         feed.startFeed(true);
229 
230         // write basic Atom feed elements
231         feed.writeFeedElements(folderInfo.getId(), folderInfo.getCreatedBy(), folderInfo.getName(),
232                 folderInfo.getLastModificationDate(), null, null);
233 
234         // write links
235         UrlBuilder baseUrl = compileBaseUrl(request, repositoryId);
236 
237         feed.writeServiceLink(baseUrl.toString(), repositoryId);
238 
239         feed.writeSelfLink(compileUrl(baseUrl, RESOURCE_DESCENDANTS, folderInfo.getId()), null);
240 
241         feed.writeViaLink(compileUrl(baseUrl, RESOURCE_ENTRY, folderInfo.getId()));
242 
243         feed.writeDownLink(compileUrl(baseUrl, RESOURCE_CHILDREN, folderInfo.getId()), Constants.MEDIATYPE_FEED);
244 
245         if (folderInfo.supportsFolderTree()) {
246             feed.writeFolderTreeLink(compileUrl(baseUrl, RESOURCE_FOLDERTREE, folderInfo.getId()));
247         }
248 
249         if (folderInfo.hasParent()) {
250             feed.writeUpLink(compileUrl(baseUrl, RESOURCE_PARENTS, folderInfo.getId()), Constants.MEDIATYPE_FEED);
251         }
252 
253         // write entries
254         AtomEntry entry = new AtomEntry(feed.getWriter());
255         for (ObjectInFolderContainer container : descendants) {
256             if ((container == null) || (container.getObject() == null) || (container.getObject().getObject() == null)) {
257                 continue;
258             }
259             writeObjectEntry(service, entry, container.getObject().getObject(), container.getChildren(), repositoryId,
260                     container.getObject().getPathSegment(), null, baseUrl, false);
261         }
262 
263         // we are done
264         feed.endFeed();
265         feed.endDocument();
266     }
267 
268     /**
269      * Folder tree feed GET.
270      */
271     public static void getFolderTree(CallContext context, CmisService service, String repositoryId,
272             HttpServletRequest request, HttpServletResponse response) throws Exception {
273         // get parameters
274         String folderId = getStringParameter(request, Constants.PARAM_ID);
275         BigInteger depth = getBigIntegerParameter(request, Constants.PARAM_DEPTH);
276         String filter = getStringParameter(request, Constants.PARAM_FILTER);
277         Boolean includeAllowableActions = getBooleanParameter(request, Constants.PARAM_ALLOWABLE_ACTIONS);
278         IncludeRelationships includeRelationships = getEnumParameter(request, Constants.PARAM_RELATIONSHIPS,
279                 IncludeRelationships.class);
280         String renditionFilter = getStringParameter(request, Constants.PARAM_RENDITION_FILTER);
281         Boolean includePathSegment = getBooleanParameter(request, Constants.PARAM_PATH_SEGMENT);
282 
283         // execute
284         List<ObjectInFolderContainer> folderTree = service.getFolderTree(repositoryId, folderId, depth, filter,
285                 includeAllowableActions, includeRelationships, renditionFilter, includePathSegment, null);
286 
287         if (folderTree == null) {
288             throw new CmisRuntimeException("Folder tree is null!");
289         }
290 
291         ObjectInfo folderInfo = service.getObjectInfo(repositoryId, folderId);
292         if (folderInfo == null) {
293             throw new CmisRuntimeException("Folder Object Info is missing!");
294         }
295 
296         // set headers
297         response.setStatus(HttpServletResponse.SC_OK);
298         response.setContentType(Constants.MEDIATYPE_FEED);
299 
300         // write XML
301         AtomFeed feed = new AtomFeed();
302         feed.startDocument(response.getOutputStream());
303         feed.startFeed(true);
304 
305         // write basic Atom feed elements
306         feed.writeFeedElements(folderInfo.getId(), folderInfo.getCreatedBy(), folderInfo.getName(),
307                 folderInfo.getLastModificationDate(), null, null);
308 
309         // write links
310         UrlBuilder baseUrl = compileBaseUrl(request, repositoryId);
311 
312         feed.writeServiceLink(baseUrl.toString(), repositoryId);
313 
314         feed.writeSelfLink(compileUrl(baseUrl, RESOURCE_DESCENDANTS, folderInfo.getId()), null);
315 
316         feed.writeViaLink(compileUrl(baseUrl, RESOURCE_ENTRY, folderInfo.getId()));
317 
318         feed.writeDownLink(compileUrl(baseUrl, RESOURCE_CHILDREN, folderInfo.getId()), Constants.MEDIATYPE_FEED);
319 
320         if (folderInfo.supportsDescendants()) {
321             feed.writeDownLink(compileUrl(baseUrl, RESOURCE_DESCENDANTS, folderInfo.getId()),
322                     Constants.MEDIATYPE_DESCENDANTS);
323         }
324 
325         if (folderInfo.hasParent()) {
326             feed.writeUpLink(compileUrl(baseUrl, RESOURCE_PARENTS, folderInfo.getId()), Constants.MEDIATYPE_FEED);
327         }
328 
329         // write entries
330         AtomEntry entry = new AtomEntry(feed.getWriter());
331         for (ObjectInFolderContainer container : folderTree) {
332             if ((container == null) || (container.getObject() == null) || (container.getObject().getObject() == null)) {
333                 continue;
334             }
335             writeObjectEntry(service, entry, container.getObject().getObject(), container.getChildren(), repositoryId,
336                     container.getObject().getPathSegment(), null, baseUrl, false);
337         }
338 
339         // we are done
340         feed.endFeed();
341         feed.endDocument();
342     }
343 
344     /**
345      * Object parents feed GET.
346      */
347     public static void getObjectParents(CallContext context, CmisService service, String repositoryId,
348             HttpServletRequest request, HttpServletResponse response) throws Exception {
349         // get parameters
350         String objectId = getStringParameter(request, Constants.PARAM_ID);
351         String filter = getStringParameter(request, Constants.PARAM_FILTER);
352         Boolean includeAllowableActions = getBooleanParameter(request, Constants.PARAM_ALLOWABLE_ACTIONS);
353         IncludeRelationships includeRelationships = getEnumParameter(request, Constants.PARAM_RELATIONSHIPS,
354                 IncludeRelationships.class);
355         String renditionFilter = getStringParameter(request, Constants.PARAM_RENDITION_FILTER);
356         Boolean includeRelativePathSegment = getBooleanParameter(request, Constants.PARAM_RELATIVE_PATH_SEGMENT);
357 
358         // execute
359         List<ObjectParentData> parents = service.getObjectParents(repositoryId, objectId, filter,
360                 includeAllowableActions, includeRelationships, renditionFilter, includeRelativePathSegment, null);
361 
362         if (parents == null) {
363             throw new CmisRuntimeException("Parents are null!");
364         }
365 
366         ObjectInfo objectInfo = service.getObjectInfo(repositoryId, objectId);
367         if (objectInfo == null) {
368             throw new CmisRuntimeException("Object Info is missing!");
369         }
370 
371         // set headers
372         response.setStatus(HttpServletResponse.SC_OK);
373         response.setContentType(Constants.MEDIATYPE_FEED);
374 
375         // write XML
376         AtomFeed feed = new AtomFeed();
377         feed.startDocument(response.getOutputStream());
378         feed.startFeed(true);
379 
380         // write basic Atom feed elements
381         feed.writeFeedElements(objectInfo.getId(), objectInfo.getCreatedBy(), objectInfo.getName(),
382                 objectInfo.getLastModificationDate(), null, null);
383 
384         // write links
385         UrlBuilder baseUrl = compileBaseUrl(request, repositoryId);
386 
387         feed.writeServiceLink(baseUrl.toString(), repositoryId);
388 
389         feed.writeSelfLink(compileUrl(baseUrl, RESOURCE_PARENTS, objectInfo.getId()), null);
390 
391         // write entries
392         AtomEntry entry = new AtomEntry(feed.getWriter());
393         for (ObjectParentData object : parents) {
394             if ((object == null) || (object.getObject() == null)) {
395                 continue;
396             }
397             writeObjectEntry(service, entry, object.getObject(), null,
398                     repositoryId, null, object.getRelativePathSegment(),
399                     baseUrl, false);
400         }
401 
402         // we are done
403         feed.endFeed();
404         feed.endDocument();
405     }
406 
407     /**
408      * Checked Out Collection GET.
409      */
410     public static void getCheckedOutDocs(CallContext context, CmisService service, String repositoryId,
411             HttpServletRequest request, HttpServletResponse response) throws Exception {
412         // get parameters
413         String folderId = getStringParameter(request, Constants.PARAM_FOLDER_ID);
414         String filter = getStringParameter(request, Constants.PARAM_FILTER);
415         String orderBy = getStringParameter(request, Constants.PARAM_ORDER_BY);
416         Boolean includeAllowableActions = getBooleanParameter(request, Constants.PARAM_ALLOWABLE_ACTIONS);
417         IncludeRelationships includeRelationships = getEnumParameter(request, Constants.PARAM_RELATIONSHIPS,
418                 IncludeRelationships.class);
419         String renditionFilter = getStringParameter(request, Constants.PARAM_RENDITION_FILTER);
420         BigInteger maxItems = getBigIntegerParameter(request, Constants.PARAM_MAX_ITEMS);
421         BigInteger skipCount = getBigIntegerParameter(request, Constants.PARAM_SKIP_COUNT);
422 
423         // execute
424         ObjectList checkedOut = service.getCheckedOutDocs(repositoryId, folderId, filter, orderBy,
425                 includeAllowableActions, includeRelationships, renditionFilter, maxItems, skipCount, null);
426 
427         if (checkedOut == null) {
428             throw new CmisRuntimeException("Checked Out list is null!");
429         }
430 
431         ObjectInfo folderInfo = null;
432         if (folderId != null) {
433             folderInfo = service.getObjectInfo(repositoryId, folderId);
434             if (folderInfo == null) {
435                 throw new CmisRuntimeException("Folder Object Info is missing!");
436             }
437         } else {
438             folderInfo = new ObjectInfoImpl();
439             GregorianCalendar now = new GregorianCalendar();
440 
441             ((ObjectInfoImpl) folderInfo).setId("uri:x-checkedout");
442             ((ObjectInfoImpl) folderInfo).setName("Checked Out");
443             ((ObjectInfoImpl) folderInfo).setCreatedBy("");
444             ((ObjectInfoImpl) folderInfo).setCreationDate(now);
445             ((ObjectInfoImpl) folderInfo).setLastModificationDate(now);
446             ((ObjectInfoImpl) folderInfo).setHasParent(false);
447             ((ObjectInfoImpl) folderInfo).setSupportsDescendants(false);
448             ((ObjectInfoImpl) folderInfo).setSupportsFolderTree(false);
449         }
450 
451         // set headers
452         response.setStatus(HttpServletResponse.SC_OK);
453         response.setContentType(Constants.MEDIATYPE_FEED);
454 
455         // write XML
456         AtomFeed feed = new AtomFeed();
457         feed.startDocument(response.getOutputStream());
458         feed.startFeed(true);
459 
460         // write basic Atom feed elements
461         feed.writeFeedElements(folderInfo.getId(), folderInfo.getCreatedBy(), folderInfo.getName(),
462                 folderInfo.getLastModificationDate(), null, checkedOut.getNumItems());
463 
464         // write links
465         UrlBuilder baseUrl = compileBaseUrl(request, repositoryId);
466 
467         feed.writeServiceLink(baseUrl.toString(), repositoryId);
468 
469         feed.writeSelfLink(compileUrl(baseUrl, RESOURCE_CHECKEDOUT, folderInfo.getId()), null);
470 
471         UrlBuilder pagingUrl = new UrlBuilder(compileUrlBuilder(baseUrl, RESOURCE_CHECKEDOUT, folderInfo.getId()));
472         pagingUrl.addParameter(Constants.PARAM_FILTER, filter);
473         pagingUrl.addParameter(Constants.PARAM_ORDER_BY, orderBy);
474         pagingUrl.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
475         pagingUrl.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
476         pagingUrl.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
477         feed.writePagingLinks(pagingUrl, maxItems, skipCount, checkedOut.getNumItems(), checkedOut.hasMoreItems(),
478                 AtomPubUtils.PAGE_SIZE);
479 
480         // write entries
481         if (checkedOut.getObjects() != null) {
482             AtomEntry entry = new AtomEntry(feed.getWriter());
483             for (ObjectData object : checkedOut.getObjects()) {
484                 if (object == null) {
485                     continue;
486                 }
487                 writeObjectEntry(service, entry, object, null, repositoryId, null, null, baseUrl, false);
488             }
489         }
490 
491         // we are done
492         feed.endFeed();
493         feed.endDocument();
494     }
495 }