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.runtime;
20
21 import static org.apache.chemistry.opencmis.commons.impl.CollectionsHelper.isNullOrEmpty;
22
23 import java.math.BigInteger;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.List;
27 import java.util.Map;
28
29 import org.apache.chemistry.opencmis.client.api.CmisObject;
30 import org.apache.chemistry.opencmis.client.api.Document;
31 import org.apache.chemistry.opencmis.client.api.FileableCmisObject;
32 import org.apache.chemistry.opencmis.client.api.Folder;
33 import org.apache.chemistry.opencmis.client.api.FolderType;
34 import org.apache.chemistry.opencmis.client.api.Item;
35 import org.apache.chemistry.opencmis.client.api.ItemIterable;
36 import org.apache.chemistry.opencmis.client.api.ObjectFactory;
37 import org.apache.chemistry.opencmis.client.api.ObjectId;
38 import org.apache.chemistry.opencmis.client.api.ObjectType;
39 import org.apache.chemistry.opencmis.client.api.OperationContext;
40 import org.apache.chemistry.opencmis.client.api.Policy;
41 import org.apache.chemistry.opencmis.client.api.Tree;
42 import org.apache.chemistry.opencmis.client.runtime.util.AbstractPageFetcher;
43 import org.apache.chemistry.opencmis.client.runtime.util.CollectionIterable;
44 import org.apache.chemistry.opencmis.client.runtime.util.TreeImpl;
45 import org.apache.chemistry.opencmis.commons.PropertyIds;
46 import org.apache.chemistry.opencmis.commons.data.Ace;
47 import org.apache.chemistry.opencmis.commons.data.ContentStream;
48 import org.apache.chemistry.opencmis.commons.data.ObjectData;
49 import org.apache.chemistry.opencmis.commons.data.ObjectInFolderContainer;
50 import org.apache.chemistry.opencmis.commons.data.ObjectInFolderData;
51 import org.apache.chemistry.opencmis.commons.data.ObjectInFolderList;
52 import org.apache.chemistry.opencmis.commons.data.ObjectList;
53 import org.apache.chemistry.opencmis.commons.data.PropertyData;
54 import org.apache.chemistry.opencmis.commons.data.PropertyId;
55 import org.apache.chemistry.opencmis.commons.data.PropertyString;
56 import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
57 import org.apache.chemistry.opencmis.commons.enums.UnfileObject;
58 import org.apache.chemistry.opencmis.commons.enums.VersioningState;
59 import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
60 import org.apache.chemistry.opencmis.commons.spi.NavigationService;
61
62 public class FolderImpl extends AbstractFilableCmisObject implements Folder {
63
64 private static final long serialVersionUID = 1L;
65
66
67
68
69 public FolderImpl(SessionImpl session, ObjectType objectType, ObjectData objectData, OperationContext context) {
70 initialize(session, objectType, objectData, context);
71 }
72
73 @Override
74 public FolderType getFolderType() {
75 ObjectType objectType = super.getType();
76 if (objectType instanceof FolderType) {
77 return (FolderType) objectType;
78 } else {
79 throw new ClassCastException("Object type is not a folder type.");
80 }
81 }
82
83 @Override
84 public Document createDocument(Map<String, ?> properties, ContentStream contentStream,
85 VersioningState versioningState, List<Policy> policies, List<Ace> addAces, List<Ace> removeAces,
86 OperationContext context) {
87
88 ObjectId newId = getSession().createDocument(properties, this, contentStream, versioningState, policies,
89 addAces, removeAces);
90
91
92 if (context == null || newId == null) {
93 return null;
94 }
95
96
97 CmisObject object = getSession().getObject(newId, context);
98 if (!(object instanceof Document)) {
99 throw new CmisRuntimeException("Newly created object is not a document! New id: " + newId);
100 }
101
102 return (Document) object;
103 }
104
105 @Override
106 public Document createDocumentFromSource(ObjectId source, Map<String, ?> properties,
107 VersioningState versioningState, List<Policy> policies, List<Ace> addAces, List<Ace> removeAces,
108 OperationContext context) {
109
110 ObjectId newId = getSession().createDocumentFromSource(source, properties, this, versioningState, policies,
111 addAces, removeAces);
112
113
114 if (context == null || newId == null) {
115 return null;
116 }
117
118
119 CmisObject object = getSession().getObject(newId, context);
120 if (!(object instanceof Document)) {
121 throw new CmisRuntimeException("Newly created object is not a document! New id: " + newId);
122 }
123
124 return (Document) object;
125 }
126
127 @Override
128 public Folder createFolder(Map<String, ?> properties, List<Policy> policies, List<Ace> addAces,
129 List<Ace> removeAces, OperationContext context) {
130
131 ObjectId newId = getSession().createFolder(properties, this, policies, addAces, removeAces);
132
133
134 if (context == null || newId == null) {
135 return null;
136 }
137
138
139 CmisObject object = getSession().getObject(newId, context);
140 if (!(object instanceof Folder)) {
141 throw new CmisRuntimeException("Newly created object is not a folder! New id: " + newId);
142 }
143
144 return (Folder) object;
145 }
146
147 @Override
148 public Policy createPolicy(Map<String, ?> properties, List<Policy> policies, List<Ace> addAces,
149 List<Ace> removeAces, OperationContext context) {
150
151 ObjectId newId = getSession().createPolicy(properties, this, policies, addAces, removeAces);
152
153
154 if (context == null || newId == null) {
155 return null;
156 }
157
158
159 CmisObject object = getSession().getObject(newId, context);
160 if (!(object instanceof Policy)) {
161 throw new CmisRuntimeException("Newly created object is not a policy! New id: " + newId);
162 }
163
164 return (Policy) object;
165 }
166
167 @Override
168 public Item createItem(Map<String, ?> properties, List<Policy> policies, List<Ace> addAces, List<Ace> removeAces,
169 OperationContext context) {
170
171 ObjectId newId = getSession().createItem(properties, this, policies, addAces, removeAces);
172
173
174 if (context == null || newId == null) {
175 return null;
176 }
177
178
179 CmisObject object = getSession().getObject(newId, context);
180 if (!(object instanceof Item)) {
181 throw new CmisRuntimeException("Newly created object is not an item! New id: " + newId);
182 }
183
184 return (Item) object;
185 }
186
187 @Override
188 public List<String> deleteTree(boolean allVersions, UnfileObject unfile, boolean continueOnFailure) {
189 return getSession().deleteTree(this, allVersions, unfile, continueOnFailure);
190 }
191
192 @Override
193 public String getParentId() {
194 return getPropertyValue(PropertyIds.PARENT_ID);
195 }
196
197 @Override
198 public List<ObjectType> getAllowedChildObjectTypes() {
199 List<ObjectType> result = new ArrayList<ObjectType>();
200
201 readLock();
202 try {
203 List<String> otids = getPropertyValue(PropertyIds.ALLOWED_CHILD_OBJECT_TYPE_IDS);
204 if (otids == null) {
205 return result;
206 }
207
208 for (String otid : otids) {
209 result.add(getSession().getTypeDefinition(otid));
210 }
211 } finally {
212 readUnlock();
213 }
214
215 return result;
216 }
217
218 @Override
219 public ItemIterable<Document> getCheckedOutDocs() {
220 return getCheckedOutDocs(getSession().getDefaultContext());
221 }
222
223 @Override
224 public ItemIterable<Document> getCheckedOutDocs(OperationContext context) {
225 final String objectId = getObjectId();
226 final NavigationService navigationService = getBinding().getNavigationService();
227 final ObjectFactory objectFactory = getSession().getObjectFactory();
228 final OperationContext ctxt = new OperationContextImpl(context);
229
230 return new CollectionIterable<Document>(new AbstractPageFetcher<Document>(ctxt.getMaxItemsPerPage()) {
231
232 @Override
233 protected AbstractPageFetcher.Page<Document> fetchPage(long skipCount) {
234
235
236 ObjectList checkedOutDocs = navigationService.getCheckedOutDocs(getRepositoryId(), objectId,
237 ctxt.getFilterString(), ctxt.getOrderBy(), ctxt.isIncludeAllowableActions(),
238 ctxt.getIncludeRelationships(), ctxt.getRenditionFilterString(),
239 BigInteger.valueOf(this.maxNumItems), BigInteger.valueOf(skipCount), null);
240
241
242 List<Document> page = new ArrayList<Document>();
243 if (checkedOutDocs.getObjects() != null) {
244 for (ObjectData objectData : checkedOutDocs.getObjects()) {
245 CmisObject doc = objectFactory.convertObject(objectData, ctxt);
246 if (!(doc instanceof Document)) {
247
248 continue;
249 }
250
251 page.add((Document) doc);
252 }
253 }
254
255 return new AbstractPageFetcher.Page<Document>(page, checkedOutDocs.getNumItems(),
256 checkedOutDocs.hasMoreItems());
257 }
258 });
259 }
260
261 @Override
262 public ItemIterable<CmisObject> getChildren() {
263 return getChildren(getSession().getDefaultContext());
264 }
265
266 @Override
267 public ItemIterable<CmisObject> getChildren(OperationContext context) {
268 final String objectId = getObjectId();
269 final NavigationService navigationService = getBinding().getNavigationService();
270 final ObjectFactory objectFactory = getSession().getObjectFactory();
271 final OperationContext ctxt = new OperationContextImpl(context);
272
273 return new CollectionIterable<CmisObject>(new AbstractPageFetcher<CmisObject>(ctxt.getMaxItemsPerPage()) {
274
275 @Override
276 protected AbstractPageFetcher.Page<CmisObject> fetchPage(long skipCount) {
277
278
279 ObjectInFolderList children = navigationService.getChildren(getRepositoryId(), objectId,
280 ctxt.getFilterString(), ctxt.getOrderBy(), ctxt.isIncludeAllowableActions(),
281 ctxt.getIncludeRelationships(), ctxt.getRenditionFilterString(), ctxt.isIncludePathSegments(),
282 BigInteger.valueOf(this.maxNumItems), BigInteger.valueOf(skipCount), null);
283
284
285 List<CmisObject> page = new ArrayList<CmisObject>();
286 List<ObjectInFolderData> childObjects = children.getObjects();
287 if (childObjects != null) {
288 for (ObjectInFolderData objectData : childObjects) {
289 if (objectData.getObject() != null) {
290 page.add(objectFactory.convertObject(objectData.getObject(), ctxt));
291 }
292 }
293 }
294
295 return new AbstractPageFetcher.Page<CmisObject>(page, children.getNumItems(), children.hasMoreItems());
296 }
297 });
298 }
299
300 @Override
301 public List<Tree<FileableCmisObject>> getDescendants(int depth) {
302 return getDescendants(depth, getSession().getDefaultContext());
303 }
304
305 @Override
306 public List<Tree<FileableCmisObject>> getDescendants(int depth, OperationContext context) {
307 String objectId = getObjectId();
308
309
310 List<ObjectInFolderContainer> providerContainerList = getBinding().getNavigationService().getDescendants(
311 getRepositoryId(), objectId, BigInteger.valueOf(depth), context.getFilterString(),
312 context.isIncludeAllowableActions(), context.getIncludeRelationships(),
313 context.getRenditionFilterString(), context.isIncludePathSegments(), null);
314
315 return convertBindingContainer(providerContainerList, context);
316 }
317
318 @Override
319 public List<Tree<FileableCmisObject>> getFolderTree(int depth) {
320 return getFolderTree(depth, getSession().getDefaultContext());
321 }
322
323 @Override
324 public List<Tree<FileableCmisObject>> getFolderTree(int depth, OperationContext context) {
325 String objectId = getObjectId();
326
327
328 List<ObjectInFolderContainer> providerContainerList = getBinding().getNavigationService().getFolderTree(
329 getRepositoryId(), objectId, BigInteger.valueOf(depth), context.getFilterString(),
330 context.isIncludeAllowableActions(), context.getIncludeRelationships(),
331 context.getRenditionFilterString(), context.isIncludePathSegments(), null);
332
333 return convertBindingContainer(providerContainerList, context);
334 }
335
336
337
338
339 private List<Tree<FileableCmisObject>> convertBindingContainer(List<ObjectInFolderContainer> bindingContainerList,
340 OperationContext context) {
341 if (bindingContainerList == null) {
342 return null;
343 }
344
345 ObjectFactory of = getSession().getObjectFactory();
346
347 List<Tree<FileableCmisObject>> result = new ArrayList<Tree<FileableCmisObject>>();
348 for (ObjectInFolderContainer oifc : bindingContainerList) {
349 if (oifc.getObject() == null || oifc.getObject().getObject() == null) {
350
351 continue;
352 }
353
354
355 CmisObject object = of.convertObject(oifc.getObject().getObject(), context);
356 if (!(object instanceof FileableCmisObject)) {
357
358
359 continue;
360 }
361
362
363 List<Tree<FileableCmisObject>> children = convertBindingContainer(oifc.getChildren(), context);
364
365
366 result.add(new TreeImpl<FileableCmisObject>((FileableCmisObject) object, children));
367 }
368
369 return result;
370 }
371
372 @Override
373 public boolean isRootFolder() {
374 String objectId = getObjectId();
375 String rootFolderId = getSession().getRepositoryInfo().getRootFolderId();
376
377 return objectId.equals(rootFolderId);
378 }
379
380 @Override
381 public Folder getFolderParent() {
382 if (isRootFolder()) {
383 return null;
384 }
385
386 List<Folder> parents = getParents(getSession().getDefaultContext());
387 if (isNullOrEmpty(parents)) {
388 return null;
389 }
390
391 return parents.get(0);
392 }
393
394 @Override
395 public String getPath() {
396 String path;
397
398 readLock();
399 try {
400
401 path = getPropertyValue(PropertyIds.PATH);
402
403
404 if (path == null) {
405 String objectId = getObjectId();
406 ObjectData objectData = getBinding().getObjectService().getObject(getRepositoryId(), objectId,
407 getPropertyQueryName(PropertyIds.PATH), false, IncludeRelationships.NONE, "cmis:none", false,
408 false, null);
409
410 if (objectData.getProperties() != null && objectData.getProperties().getProperties() != null) {
411 PropertyData<?> pathProperty = objectData.getProperties().getProperties().get(PropertyIds.PATH);
412
413 if (pathProperty instanceof PropertyString) {
414 path = ((PropertyString) pathProperty).getFirstValue();
415 }
416 }
417 }
418 } finally {
419 readUnlock();
420 }
421
422
423 if (path == null) {
424 throw new CmisRuntimeException("Repository didn't return " + PropertyIds.PATH + "!");
425 }
426
427 return path;
428 }
429
430 @Override
431 public List<Folder> getParents(OperationContext context) {
432 if (isRootFolder()) {
433 return Collections.emptyList();
434 }
435
436 String objectId = getObjectId();
437
438 ObjectData bindingParent = getBinding().getNavigationService().getFolderParent(getRepositoryId(), objectId,
439 getPropertyQueryName(PropertyIds.OBJECT_ID), null);
440
441 if (bindingParent.getProperties() == null) {
442
443 throw new CmisRuntimeException("Repository sent invalid data!");
444 }
445
446
447 PropertyData<?> idProperty = bindingParent.getProperties().getProperties().get(PropertyIds.OBJECT_ID);
448 if (!(idProperty instanceof PropertyId) && !(idProperty instanceof PropertyString)) {
449
450 throw new CmisRuntimeException("Repository sent invalid data! No object id!");
451 }
452
453
454 CmisObject parentFolder = getSession().getObject((String) idProperty.getFirstValue(), context);
455 if (!(parentFolder instanceof Folder)) {
456
457 throw new CmisRuntimeException("Repository sent invalid data! Object is not a folder!");
458 }
459
460 return Collections.singletonList((Folder) parentFolder);
461 }
462
463 @Override
464 public List<String> getPaths() {
465 return Collections.singletonList(getPath());
466 }
467
468 @Override
469 public Document createDocument(Map<String, ?> properties, ContentStream contentStream,
470 VersioningState versioningState) {
471 return this.createDocument(properties, contentStream, versioningState, null, null, null, getSession()
472 .getDefaultContext());
473 }
474
475 @Override
476 public Document createDocumentFromSource(ObjectId source, Map<String, ?> properties, VersioningState versioningState) {
477 return this.createDocumentFromSource(source, properties, versioningState, null, null, null, getSession()
478 .getDefaultContext());
479 }
480
481 @Override
482 public Folder createFolder(Map<String, ?> properties) {
483 return this.createFolder(properties, null, null, null, getSession().getDefaultContext());
484 }
485
486 @Override
487 public Policy createPolicy(Map<String, ?> properties) {
488 return this.createPolicy(properties, null, null, null, getSession().getDefaultContext());
489 }
490
491 @Override
492 public Item createItem(Map<String, ?> properties) {
493 return this.createItem(properties, null, null, null, getSession().getDefaultContext());
494 }
495 }