This project has retired. For details please refer to its Attic page.
NavigationServiceImpl 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.client.bindings.spi.atompub;
20  
21  import static org.apache.chemistry.opencmis.commons.impl.Converter.convert;
22  
23  import java.math.BigInteger;
24  import java.util.ArrayList;
25  import java.util.List;
26  
27  import org.apache.chemistry.opencmis.client.bindings.spi.BindingSession;
28  import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomBase;
29  import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomElement;
30  import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomEntry;
31  import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomFeed;
32  import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomLink;
33  import org.apache.chemistry.opencmis.client.bindings.spi.http.HttpUtils;
34  import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
35  import org.apache.chemistry.opencmis.commons.data.ObjectData;
36  import org.apache.chemistry.opencmis.commons.data.ObjectInFolderContainer;
37  import org.apache.chemistry.opencmis.commons.data.ObjectInFolderData;
38  import org.apache.chemistry.opencmis.commons.data.ObjectInFolderList;
39  import org.apache.chemistry.opencmis.commons.data.ObjectList;
40  import org.apache.chemistry.opencmis.commons.data.ObjectParentData;
41  import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
42  import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
43  import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
44  import org.apache.chemistry.opencmis.commons.impl.Constants;
45  import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
46  import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderContainerImpl;
47  import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderDataImpl;
48  import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderListImpl;
49  import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectListImpl;
50  import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectParentDataImpl;
51  import org.apache.chemistry.opencmis.commons.impl.jaxb.CmisObjectType;
52  import org.apache.chemistry.opencmis.commons.spi.NavigationService;
53  
54  /**
55   * Navigation Service AtomPub client.
56   *
57   * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
58   */
59  public class NavigationServiceImpl extends AbstractAtomPubService implements NavigationService {
60  
61      /**
62       * Constructor.
63       */
64      public NavigationServiceImpl(BindingSession session) {
65          setSession(session);
66      }
67  
68      public ObjectInFolderList getChildren(String repositoryId, String folderId, String filter, String orderBy,
69              Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
70              Boolean includePathSegment, BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {
71          ObjectInFolderListImpl result = new ObjectInFolderListImpl();
72  
73          // find the link
74          String link = loadLink(repositoryId, folderId, Constants.REL_DOWN, Constants.MEDIATYPE_CHILDREN);
75  
76          if (link == null) {
77              throwLinkException(repositoryId, folderId, Constants.REL_DOWN, Constants.MEDIATYPE_CHILDREN);
78          }
79  
80          UrlBuilder url = new UrlBuilder(link);
81          url.addParameter(Constants.PARAM_FILTER, filter);
82          url.addParameter(Constants.PARAM_ORDER_BY, orderBy);
83          url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
84          url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
85          url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
86          url.addParameter(Constants.PARAM_PATH_SEGMENT, includePathSegment);
87          url.addParameter(Constants.PARAM_MAX_ITEMS, maxItems);
88          url.addParameter(Constants.PARAM_SKIP_COUNT, skipCount);
89  
90          // read and parse
91          HttpUtils.Response resp = read(url);
92          AtomFeed feed = parse(resp.getStream(), AtomFeed.class);
93  
94          // handle top level
95          for (AtomElement element : feed.getElements()) {
96              if (element.getObject() instanceof AtomLink) {
97                  if (isNextLink(element)) {
98                      result.setHasMoreItems(Boolean.TRUE);
99                  }
100             } else if (isInt(NAME_NUM_ITEMS, element)) {
101                 result.setNumItems((BigInteger) element.getObject());
102             }
103         }
104 
105         // get the children
106         if (!feed.getEntries().isEmpty()) {
107             result.setObjects(new ArrayList<ObjectInFolderData>(feed.getEntries().size()));
108 
109             for (AtomEntry entry : feed.getEntries()) {
110                 ObjectInFolderDataImpl child = null;
111                 String pathSegment = null;
112 
113                 lockLinks();
114                 try {
115                     // clean up cache
116                     removeLinks(repositoryId, entry.getId());
117 
118                     // walk through the entry
119                     for (AtomElement element : entry.getElements()) {
120                         if (element.getObject() instanceof AtomLink) {
121                             addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
122                         } else if (isStr(NAME_PATH_SEGMENT, element)) {
123                             pathSegment = (String) element.getObject();
124                         } else if (element.getObject() instanceof CmisObjectType) {
125                             child = new ObjectInFolderDataImpl();
126                             child.setObject(convert((CmisObjectType) element.getObject()));
127                         }
128                     }
129                 } finally {
130                     unlockLinks();
131                 }
132 
133                 if (child != null) {
134                     child.setPathSegment(pathSegment);
135                     result.getObjects().add(child);
136                 }
137             }
138         }
139 
140         return result;
141     }
142 
143     public List<ObjectInFolderContainer> getDescendants(String repositoryId, String folderId, BigInteger depth,
144             String filter, Boolean includeAllowableActions, IncludeRelationships includeRelationships,
145             String renditionFilter, Boolean includePathSegment, ExtensionsData extension) {
146         List<ObjectInFolderContainer> result = new ArrayList<ObjectInFolderContainer>();
147 
148         // find the link
149         String link = loadLink(repositoryId, folderId, Constants.REL_DOWN, Constants.MEDIATYPE_DESCENDANTS);
150 
151         if (link == null) {
152             throwLinkException(repositoryId, folderId, Constants.REL_DOWN, Constants.MEDIATYPE_DESCENDANTS);
153         }
154 
155         UrlBuilder url = new UrlBuilder(link);
156         url.addParameter(Constants.PARAM_DEPTH, depth);
157         url.addParameter(Constants.PARAM_FILTER, filter);
158         url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
159         url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
160         url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
161         url.addParameter(Constants.PARAM_PATH_SEGMENT, includePathSegment);
162 
163         // read and parse
164         HttpUtils.Response resp = read(url);
165         AtomFeed feed = parse(resp.getStream(), AtomFeed.class);
166 
167         // process tree
168         addDescendantsLevel(repositoryId, feed, result);
169 
170         return result;
171     }
172 
173     public ObjectData getFolderParent(String repositoryId, String folderId, String filter, ExtensionsData extension) {
174         ObjectData result = null;
175 
176         // find the link
177         String link = loadLink(repositoryId, folderId, Constants.REL_UP, Constants.MEDIATYPE_ENTRY);
178 
179         if (link == null) {
180             throwLinkException(repositoryId, folderId, Constants.REL_UP, Constants.MEDIATYPE_ENTRY);
181         }
182 
183         UrlBuilder url = new UrlBuilder(link);
184         url.addParameter(Constants.PARAM_FILTER, filter);
185 
186         // read
187         HttpUtils.Response resp = read(url);
188 
189         AtomBase base = parse(resp.getStream(), AtomBase.class);
190 
191         // get the entry
192         AtomEntry entry = null;
193         if (base instanceof AtomFeed) {
194             AtomFeed feed = (AtomFeed) base;
195             if (feed.getEntries().isEmpty()) {
196                 throw new CmisRuntimeException("Parent feed is empty!");
197             }
198             entry = feed.getEntries().get(0);
199         } else if (base instanceof AtomEntry) {
200             entry = (AtomEntry) base;
201         } else {
202             throw new CmisRuntimeException("Unexpected document!");
203         }
204 
205         lockLinks();
206         try {
207             // clean up cache
208             removeLinks(repositoryId, entry.getId());
209 
210             // walk through the entry
211             for (AtomElement element : entry.getElements()) {
212                 if (element.getObject() instanceof AtomLink) {
213                     addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
214                 } else if (element.getObject() instanceof CmisObjectType) {
215                     result = convert((CmisObjectType) element.getObject());
216                 }
217             }
218         } finally {
219             unlockLinks();
220         }
221 
222         return result;
223     }
224 
225     public List<ObjectInFolderContainer> getFolderTree(String repositoryId, String folderId, BigInteger depth,
226             String filter, Boolean includeAllowableActions, IncludeRelationships includeRelationships,
227             String renditionFilter, Boolean includePathSegment, ExtensionsData extension) {
228         List<ObjectInFolderContainer> result = new ArrayList<ObjectInFolderContainer>();
229 
230         // find the link
231         String link = loadLink(repositoryId, folderId, Constants.REL_FOLDERTREE, Constants.MEDIATYPE_DESCENDANTS);
232 
233         if (link == null) {
234             throwLinkException(repositoryId, folderId, Constants.REL_FOLDERTREE, Constants.MEDIATYPE_DESCENDANTS);
235         }
236 
237         UrlBuilder url = new UrlBuilder(link);
238         url.addParameter(Constants.PARAM_DEPTH, depth);
239         url.addParameter(Constants.PARAM_FILTER, filter);
240         url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
241         url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
242         url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
243         url.addParameter(Constants.PARAM_PATH_SEGMENT, includePathSegment);
244 
245         // read and parse
246         HttpUtils.Response resp = read(url);
247         AtomFeed feed = parse(resp.getStream(), AtomFeed.class);
248 
249         // process tree
250         addDescendantsLevel(repositoryId, feed, result);
251 
252         return result;
253     }
254 
255     public List<ObjectParentData> getObjectParents(String repositoryId, String objectId, String filter,
256             Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
257             Boolean includeRelativePathSegment, ExtensionsData extension) {
258         List<ObjectParentData> result = new ArrayList<ObjectParentData>();
259 
260         // find the link
261         String link = loadLink(repositoryId, objectId, Constants.REL_UP, Constants.MEDIATYPE_FEED);
262 
263         if (link == null) {
264             // root and unfiled objects have no UP link
265             return result;
266         }
267 
268         UrlBuilder url = new UrlBuilder(link);
269         url.addParameter(Constants.PARAM_FILTER, filter);
270         url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
271         url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
272         url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
273         url.addParameter(Constants.PARAM_RELATIVE_PATH_SEGMENT, includeRelativePathSegment);
274 
275         // read and parse
276         HttpUtils.Response resp = read(url);
277 
278         AtomBase base = parse(resp.getStream(), AtomBase.class);
279 
280         if (base instanceof AtomFeed) {
281             // it's a feed
282             AtomFeed feed = (AtomFeed) base;
283 
284             // walk through the feed
285             for (AtomEntry entry : feed.getEntries()) {
286                 ObjectParentDataImpl objectParent = processParentEntry(entry, repositoryId);
287 
288                 if (objectParent != null) {
289                     result.add(objectParent);
290                 }
291             }
292         } else if (base instanceof AtomEntry) {
293             // it's an entry
294             AtomEntry entry = (AtomEntry) base;
295 
296             ObjectParentDataImpl objectParent = processParentEntry(entry, repositoryId);
297 
298             if (objectParent != null) {
299                 result.add(objectParent);
300             }
301         }
302 
303         return result;
304     }
305 
306     private ObjectParentDataImpl processParentEntry(AtomEntry entry, String repositoryId) {
307         ObjectParentDataImpl result = null;
308         String relativePathSegment = null;
309 
310         lockLinks();
311         try {
312             // clean up cache
313             removeLinks(repositoryId, entry.getId());
314 
315             // walk through the entry
316             for (AtomElement element : entry.getElements()) {
317                 if (element.getObject() instanceof AtomLink) {
318                     addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
319                 } else if (element.getObject() instanceof CmisObjectType) {
320                     result = new ObjectParentDataImpl(convert((CmisObjectType) element.getObject()));
321                 } else if (is(NAME_RELATIVE_PATH_SEGMENT, element)) {
322                     relativePathSegment = (String) element.getObject();
323                 }
324             }
325         } finally {
326             unlockLinks();
327         }
328 
329         if (result != null) {
330             result.setRelativePathSegment(relativePathSegment);
331         }
332 
333         return result;
334     }
335 
336     public ObjectList getCheckedOutDocs(String repositoryId, String folderId, String filter, String orderBy,
337             Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
338             BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {
339         ObjectListImpl result = new ObjectListImpl();
340 
341         // find the link
342         String link = loadCollection(repositoryId, Constants.COLLECTION_CHECKEDOUT);
343 
344         if (link == null) {
345             throw new CmisObjectNotFoundException("Unknown repository or checkedout collection not supported!");
346         }
347 
348         UrlBuilder url = new UrlBuilder(link);
349         url.addParameter(Constants.PARAM_FOLDER_ID, folderId);
350         url.addParameter(Constants.PARAM_FILTER, filter);
351         url.addParameter(Constants.PARAM_ORDER_BY, orderBy);
352         url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
353         url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
354         url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
355         url.addParameter(Constants.PARAM_MAX_ITEMS, maxItems);
356         url.addParameter(Constants.PARAM_SKIP_COUNT, skipCount);
357 
358         // read and parse
359         HttpUtils.Response resp = read(url);
360         AtomFeed feed = parse(resp.getStream(), AtomFeed.class);
361 
362         // handle top level
363         for (AtomElement element : feed.getElements()) {
364             if (element.getObject() instanceof AtomLink) {
365                 if (isNextLink(element)) {
366                     result.setHasMoreItems(Boolean.TRUE);
367                 }
368             } else if (isInt(NAME_NUM_ITEMS, element)) {
369                 result.setNumItems((BigInteger) element.getObject());
370             }
371         }
372 
373         // get the documents
374         if (!feed.getEntries().isEmpty()) {
375             result.setObjects(new ArrayList<ObjectData>(feed.getEntries().size()));
376 
377             for (AtomEntry entry : feed.getEntries()) {
378                 ObjectData child = null;
379 
380                 lockLinks();
381                 try {
382                     // clean up cache
383                     removeLinks(repositoryId, entry.getId());
384 
385                     // walk through the entry
386                     for (AtomElement element : entry.getElements()) {
387                         if (element.getObject() instanceof AtomLink) {
388                             addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
389                         } else if (element.getObject() instanceof CmisObjectType) {
390                             child = convert((CmisObjectType) element.getObject());
391                         }
392                     }
393                 } finally {
394                     unlockLinks();
395                 }
396 
397                 if (child != null) {
398                     result.getObjects().add(child);
399                 }
400             }
401         }
402 
403         return result;
404     }
405 
406     // ---- internal ----
407 
408     /**
409      * Adds descendants level recursively.
410      */
411     private void addDescendantsLevel(String repositoryId, AtomFeed feed, List<ObjectInFolderContainer> containerList) {
412         if ((feed == null) || (feed.getEntries().isEmpty())) {
413             return;
414         }
415 
416         // walk through the feed
417         for (AtomEntry entry : feed.getEntries()) {
418             ObjectInFolderDataImpl objectInFolder = null;
419             String pathSegment = null;
420             List<ObjectInFolderContainer> childContainerList = new ArrayList<ObjectInFolderContainer>();
421 
422             lockLinks();
423             try {
424                 // clean up cache
425                 removeLinks(repositoryId, entry.getId());
426 
427                 // walk through the entry
428                 for (AtomElement element : entry.getElements()) {
429                     if (element.getObject() instanceof AtomLink) {
430                         addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
431                     } else if (element.getObject() instanceof CmisObjectType) {
432                         objectInFolder = new ObjectInFolderDataImpl(convert((CmisObjectType) element.getObject()));
433                     } else if (is(NAME_PATH_SEGMENT, element)) {
434                         pathSegment = (String) element.getObject();
435                     } else if (element.getObject() instanceof AtomFeed) {
436                         addDescendantsLevel(repositoryId, (AtomFeed) element.getObject(), childContainerList);
437                     }
438                 }
439             } finally {
440                 unlockLinks();
441             }
442 
443             if (objectInFolder != null) {
444                 objectInFolder.setPathSegment(pathSegment);
445                 ObjectInFolderContainerImpl childContainer = new ObjectInFolderContainerImpl(objectInFolder);
446                 childContainer.setChildren(childContainerList);
447                 containerList.add(childContainer);
448             }
449         }
450     }
451 }