1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.chemistry.opencmis.client.bindings.spi.atompub;
20
21 import java.math.BigInteger;
22 import java.util.ArrayList;
23 import java.util.List;
24
25 import org.apache.chemistry.opencmis.client.bindings.spi.BindingSession;
26 import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomBase;
27 import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomElement;
28 import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomEntry;
29 import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomFeed;
30 import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomLink;
31 import org.apache.chemistry.opencmis.client.bindings.spi.http.Response;
32 import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
33 import org.apache.chemistry.opencmis.commons.data.ObjectData;
34 import org.apache.chemistry.opencmis.commons.data.ObjectInFolderContainer;
35 import org.apache.chemistry.opencmis.commons.data.ObjectInFolderData;
36 import org.apache.chemistry.opencmis.commons.data.ObjectInFolderList;
37 import org.apache.chemistry.opencmis.commons.data.ObjectList;
38 import org.apache.chemistry.opencmis.commons.data.ObjectParentData;
39 import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
40 import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
41 import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
42 import org.apache.chemistry.opencmis.commons.impl.Constants;
43 import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
44 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderContainerImpl;
45 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderDataImpl;
46 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderListImpl;
47 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectListImpl;
48 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectParentDataImpl;
49 import org.apache.chemistry.opencmis.commons.spi.NavigationService;
50
51
52
53
54 public class NavigationServiceImpl extends AbstractAtomPubService implements NavigationService {
55
56
57
58
59 public NavigationServiceImpl(BindingSession session) {
60 setSession(session);
61 }
62
63 @Override
64 public ObjectInFolderList getChildren(String repositoryId, String folderId, String filter, String orderBy,
65 Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
66 Boolean includePathSegment, BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {
67 ObjectInFolderListImpl result = new ObjectInFolderListImpl();
68
69
70 String link = loadLink(repositoryId, folderId, Constants.REL_DOWN, Constants.MEDIATYPE_CHILDREN);
71
72 if (link == null) {
73 throwLinkException(repositoryId, folderId, Constants.REL_DOWN, Constants.MEDIATYPE_CHILDREN);
74 }
75
76 UrlBuilder url = new UrlBuilder(link);
77 url.addParameter(Constants.PARAM_FILTER, filter);
78 url.addParameter(Constants.PARAM_ORDER_BY, orderBy);
79 url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
80 url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
81 url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
82 url.addParameter(Constants.PARAM_PATH_SEGMENT, includePathSegment);
83 url.addParameter(Constants.PARAM_MAX_ITEMS, maxItems);
84 url.addParameter(Constants.PARAM_SKIP_COUNT, skipCount);
85
86
87 Response resp = read(url);
88 AtomFeed feed = parse(resp.getStream(), AtomFeed.class);
89
90
91 for (AtomElement element : feed.getElements()) {
92 if (element.getObject() instanceof AtomLink) {
93 if (isNextLink(element)) {
94 result.setHasMoreItems(Boolean.TRUE);
95 }
96 } else if (isInt(NAME_NUM_ITEMS, element)) {
97 result.setNumItems((BigInteger) element.getObject());
98 }
99 }
100
101
102 if (!feed.getEntries().isEmpty()) {
103 result.setObjects(new ArrayList<ObjectInFolderData>(feed.getEntries().size()));
104
105 for (AtomEntry entry : feed.getEntries()) {
106 ObjectInFolderDataImpl child = null;
107 String pathSegment = null;
108
109 lockLinks();
110 try {
111
112 removeLinks(repositoryId, entry.getId());
113
114
115 for (AtomElement element : entry.getElements()) {
116 if (element.getObject() instanceof AtomLink) {
117 addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
118 } else if (isStr(NAME_PATH_SEGMENT, element)) {
119 pathSegment = (String) element.getObject();
120 } else if (element.getObject() instanceof ObjectData) {
121 child = new ObjectInFolderDataImpl();
122 child.setObject((ObjectData) element.getObject());
123 }
124 }
125 } finally {
126 unlockLinks();
127 }
128
129 if (child != null) {
130 child.setPathSegment(pathSegment);
131 result.getObjects().add(child);
132 }
133 }
134 }
135
136 return result;
137 }
138
139 @Override
140 public List<ObjectInFolderContainer> getDescendants(String repositoryId, String folderId, BigInteger depth,
141 String filter, Boolean includeAllowableActions, IncludeRelationships includeRelationships,
142 String renditionFilter, Boolean includePathSegment, ExtensionsData extension) {
143 List<ObjectInFolderContainer> result = new ArrayList<ObjectInFolderContainer>();
144
145
146 String link = loadLink(repositoryId, folderId, Constants.REL_DOWN, Constants.MEDIATYPE_DESCENDANTS);
147
148 if (link == null) {
149 throwLinkException(repositoryId, folderId, Constants.REL_DOWN, Constants.MEDIATYPE_DESCENDANTS);
150 }
151
152 UrlBuilder url = new UrlBuilder(link);
153 url.addParameter(Constants.PARAM_DEPTH, depth);
154 url.addParameter(Constants.PARAM_FILTER, filter);
155 url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
156 url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
157 url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
158 url.addParameter(Constants.PARAM_PATH_SEGMENT, includePathSegment);
159
160
161 Response resp = read(url);
162 AtomFeed feed = parse(resp.getStream(), AtomFeed.class);
163
164
165 addDescendantsLevel(repositoryId, feed, result);
166
167 return result;
168 }
169
170 @Override
171 public ObjectData getFolderParent(String repositoryId, String folderId, String filter, ExtensionsData extension) {
172 ObjectData result = null;
173
174
175 String link = loadLink(repositoryId, folderId, Constants.REL_UP, Constants.MEDIATYPE_ENTRY);
176
177 if (link == null) {
178 throwLinkException(repositoryId, folderId, Constants.REL_UP, Constants.MEDIATYPE_ENTRY);
179 }
180
181 UrlBuilder url = new UrlBuilder(link);
182 url.addParameter(Constants.PARAM_FILTER, filter);
183
184
185 Response resp = read(url);
186
187 AtomBase base = parse(resp.getStream(), AtomBase.class);
188
189
190 AtomEntry entry = null;
191 if (base instanceof AtomFeed) {
192 AtomFeed feed = (AtomFeed) base;
193 if (feed.getEntries().isEmpty()) {
194 throw new CmisRuntimeException("Parent feed is empty!");
195 }
196 entry = feed.getEntries().get(0);
197 } else if (base instanceof AtomEntry) {
198 entry = (AtomEntry) base;
199 } else {
200 throw new CmisRuntimeException("Unexpected document!");
201 }
202
203 lockLinks();
204 try {
205
206 removeLinks(repositoryId, entry.getId());
207
208
209 for (AtomElement element : entry.getElements()) {
210 if (element.getObject() instanceof AtomLink) {
211 addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
212 } else if (element.getObject() instanceof ObjectData) {
213 result = (ObjectData) element.getObject();
214 }
215 }
216 } finally {
217 unlockLinks();
218 }
219
220 return result;
221 }
222
223 @Override
224 public List<ObjectInFolderContainer> getFolderTree(String repositoryId, String folderId, BigInteger depth,
225 String filter, Boolean includeAllowableActions, IncludeRelationships includeRelationships,
226 String renditionFilter, Boolean includePathSegment, ExtensionsData extension) {
227 List<ObjectInFolderContainer> result = new ArrayList<ObjectInFolderContainer>();
228
229
230 String link = loadLink(repositoryId, folderId, Constants.REL_FOLDERTREE, Constants.MEDIATYPE_DESCENDANTS);
231
232 if (link == null) {
233 throwLinkException(repositoryId, folderId, Constants.REL_FOLDERTREE, Constants.MEDIATYPE_DESCENDANTS);
234 }
235
236 UrlBuilder url = new UrlBuilder(link);
237 url.addParameter(Constants.PARAM_DEPTH, depth);
238 url.addParameter(Constants.PARAM_FILTER, filter);
239 url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
240 url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
241 url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
242 url.addParameter(Constants.PARAM_PATH_SEGMENT, includePathSegment);
243
244
245 Response resp = read(url);
246 AtomFeed feed = parse(resp.getStream(), AtomFeed.class);
247
248
249 addDescendantsLevel(repositoryId, feed, result);
250
251 return result;
252 }
253
254 @Override
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
261 String link = loadLink(repositoryId, objectId, Constants.REL_UP, Constants.MEDIATYPE_FEED);
262
263 if (link == null) {
264
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
276 Response resp = read(url);
277
278 AtomBase base = parse(resp.getStream(), AtomBase.class);
279
280 if (base instanceof AtomFeed) {
281
282 AtomFeed feed = (AtomFeed) base;
283
284
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
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
313 removeLinks(repositoryId, entry.getId());
314
315
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 ObjectData) {
320 result = new ObjectParentDataImpl((ObjectData) 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 @Override
337 public ObjectList getCheckedOutDocs(String repositoryId, String folderId, String filter, String orderBy,
338 Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
339 BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {
340 ObjectListImpl result = new ObjectListImpl();
341
342
343 String link = loadCollection(repositoryId, Constants.COLLECTION_CHECKEDOUT);
344
345 if (link == null) {
346 throw new CmisObjectNotFoundException("Unknown repository or checkedout collection not supported!");
347 }
348
349 UrlBuilder url = new UrlBuilder(link);
350 url.addParameter(Constants.PARAM_FOLDER_ID, folderId);
351 url.addParameter(Constants.PARAM_FILTER, filter);
352 url.addParameter(Constants.PARAM_ORDER_BY, orderBy);
353 url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
354 url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
355 url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
356 url.addParameter(Constants.PARAM_MAX_ITEMS, maxItems);
357 url.addParameter(Constants.PARAM_SKIP_COUNT, skipCount);
358
359
360 Response resp = read(url);
361 AtomFeed feed = parse(resp.getStream(), AtomFeed.class);
362
363
364 for (AtomElement element : feed.getElements()) {
365 if (element.getObject() instanceof AtomLink) {
366 if (isNextLink(element)) {
367 result.setHasMoreItems(Boolean.TRUE);
368 }
369 } else if (isInt(NAME_NUM_ITEMS, element)) {
370 result.setNumItems((BigInteger) element.getObject());
371 }
372 }
373
374
375 if (!feed.getEntries().isEmpty()) {
376 result.setObjects(new ArrayList<ObjectData>(feed.getEntries().size()));
377
378 for (AtomEntry entry : feed.getEntries()) {
379 ObjectData child = null;
380
381 lockLinks();
382 try {
383
384 removeLinks(repositoryId, entry.getId());
385
386
387 for (AtomElement element : entry.getElements()) {
388 if (element.getObject() instanceof AtomLink) {
389 addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
390 } else if (element.getObject() instanceof ObjectData) {
391 child = (ObjectData) element.getObject();
392 }
393 }
394 } finally {
395 unlockLinks();
396 }
397
398 if (child != null) {
399 result.getObjects().add(child);
400 }
401 }
402 }
403
404 return result;
405 }
406
407
408
409
410
411
412 private void addDescendantsLevel(String repositoryId, AtomFeed feed, List<ObjectInFolderContainer> containerList) {
413 if (feed == null || feed.getEntries().isEmpty()) {
414 return;
415 }
416
417
418 for (AtomEntry entry : feed.getEntries()) {
419 ObjectInFolderDataImpl objectInFolder = null;
420 String pathSegment = null;
421 List<ObjectInFolderContainer> childContainerList = new ArrayList<ObjectInFolderContainer>();
422
423 lockLinks();
424 try {
425
426 removeLinks(repositoryId, entry.getId());
427
428
429 for (AtomElement element : entry.getElements()) {
430 if (element.getObject() instanceof AtomLink) {
431 addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
432 } else if (element.getObject() instanceof ObjectData) {
433 objectInFolder = new ObjectInFolderDataImpl((ObjectData) element.getObject());
434 } else if (is(NAME_PATH_SEGMENT, element)) {
435 pathSegment = (String) element.getObject();
436 } else if (element.getObject() instanceof AtomFeed) {
437 addDescendantsLevel(repositoryId, (AtomFeed) element.getObject(), childContainerList);
438 }
439 }
440 } finally {
441 unlockLinks();
442 }
443
444 if (objectInFolder != null) {
445 objectInFolder.setPathSegment(pathSegment);
446 ObjectInFolderContainerImpl childContainer = new ObjectInFolderContainerImpl(objectInFolder);
447 childContainer.setChildren(childContainerList);
448 containerList.add(childContainer);
449 }
450 }
451 }
452 }