This project has retired. For details please refer to its
Attic page.
AbstractCmisObject xref
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.isNotEmpty;
22 import static org.apache.chemistry.opencmis.commons.impl.CollectionsHelper.isNullOrEmpty;
23
24 import java.io.Serializable;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.EnumMap;
28 import java.util.EnumSet;
29 import java.util.GregorianCalendar;
30 import java.util.HashMap;
31 import java.util.HashSet;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Set;
35 import java.util.concurrent.locks.ReentrantReadWriteLock;
36
37 import org.apache.chemistry.opencmis.client.api.CmisObject;
38 import org.apache.chemistry.opencmis.client.api.ObjectFactory;
39 import org.apache.chemistry.opencmis.client.api.ObjectId;
40 import org.apache.chemistry.opencmis.client.api.ObjectType;
41 import org.apache.chemistry.opencmis.client.api.OperationContext;
42 import org.apache.chemistry.opencmis.client.api.Policy;
43 import org.apache.chemistry.opencmis.client.api.Property;
44 import org.apache.chemistry.opencmis.client.api.Relationship;
45 import org.apache.chemistry.opencmis.client.api.Rendition;
46 import org.apache.chemistry.opencmis.client.api.SecondaryType;
47 import org.apache.chemistry.opencmis.commons.PropertyIds;
48 import org.apache.chemistry.opencmis.commons.data.Ace;
49 import org.apache.chemistry.opencmis.commons.data.Acl;
50 import org.apache.chemistry.opencmis.commons.data.AllowableActions;
51 import org.apache.chemistry.opencmis.commons.data.CmisExtensionElement;
52 import org.apache.chemistry.opencmis.commons.data.ObjectData;
53 import org.apache.chemistry.opencmis.commons.data.RenditionData;
54 import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
55 import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
56 import org.apache.chemistry.opencmis.commons.enums.Action;
57 import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
58 import org.apache.chemistry.opencmis.commons.enums.ExtensionLevel;
59 import org.apache.chemistry.opencmis.commons.enums.Updatability;
60 import org.apache.chemistry.opencmis.commons.spi.CmisBinding;
61 import org.apache.chemistry.opencmis.commons.spi.Holder;
62
63
64
65
66 public abstract class AbstractCmisObject implements CmisObject, Serializable {
67
68 private static final long serialVersionUID = 1L;
69
70 private SessionImpl session;
71 private ObjectType objectType;
72 private List<SecondaryType> secondaryTypes;
73 private Map<String, Property<?>> properties;
74 private AllowableActions allowableActions;
75 private List<Rendition> renditions;
76 private Acl acl;
77 private List<Policy> policies;
78 private List<Relationship> relationships;
79 private Map<ExtensionLevel, List<CmisExtensionElement>> extensions;
80 private OperationContext creationContext;
81 private long refreshTimestamp;
82
83 private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
84
85
86
87
88 protected void initialize(SessionImpl session, ObjectType objectType, ObjectData objectData,
89 OperationContext context) {
90 if (session == null) {
91 throw new IllegalArgumentException("Session must be set!");
92 }
93
94 if (objectType == null) {
95 throw new IllegalArgumentException("Object type must be set!");
96 }
97
98 if (objectType.getPropertyDefinitions() == null || objectType.getPropertyDefinitions().size() < 9) {
99
100
101 throw new IllegalArgumentException("Object type must have property definitions!");
102 }
103
104 if (objectData == null) {
105 throw new IllegalArgumentException("Object data must be set!");
106 }
107
108 if (objectData.getProperties() == null) {
109 throw new IllegalArgumentException("Properties must be set!");
110 }
111
112 if (objectData.getId() == null) {
113 throw new IllegalArgumentException("Object ID must be set!");
114 }
115
116 this.session = session;
117 this.objectType = objectType;
118 this.secondaryTypes = null;
119 this.extensions = new EnumMap<ExtensionLevel, List<CmisExtensionElement>>(ExtensionLevel.class);
120 this.creationContext = new OperationContextImpl(context);
121 this.refreshTimestamp = System.currentTimeMillis();
122
123 ObjectFactory of = getObjectFactory();
124
125
126 if (objectData.getProperties().getProperties() != null
127 && objectData.getProperties().getProperties().containsKey(PropertyIds.SECONDARY_OBJECT_TYPE_IDS)) {
128 @SuppressWarnings("unchecked")
129 List<String> stids = (List<String>) objectData.getProperties().getProperties()
130 .get(PropertyIds.SECONDARY_OBJECT_TYPE_IDS).getValues();
131 if (isNotEmpty(stids)) {
132 secondaryTypes = new ArrayList<SecondaryType>();
133 for (String stid : stids) {
134 if (stid != null) {
135 ObjectType type = session.getTypeDefinition(stid);
136 if (type instanceof SecondaryType) {
137 secondaryTypes.add((SecondaryType) type);
138 }
139 }
140 }
141 } else {
142 secondaryTypes = null;
143 }
144 }
145
146
147 this.properties = of.convertProperties(objectType, secondaryTypes, objectData.getProperties());
148 extensions.put(ExtensionLevel.PROPERTIES, objectData.getProperties().getExtensions());
149
150
151 if (objectData.getAllowableActions() != null) {
152 allowableActions = objectData.getAllowableActions();
153 extensions.put(ExtensionLevel.ALLOWABLE_ACTIONS, objectData.getAllowableActions().getExtensions());
154 } else {
155 allowableActions = null;
156 }
157
158
159 if (objectData.getRenditions() != null && !objectData.getRenditions().isEmpty()) {
160 renditions = new ArrayList<Rendition>();
161 for (RenditionData rd : objectData.getRenditions()) {
162 renditions.add(of.convertRendition(getId(), rd));
163 }
164 } else {
165 renditions = null;
166 }
167
168
169 if (objectData.getAcl() != null) {
170 acl = objectData.getAcl();
171 extensions.put(ExtensionLevel.ACL, objectData.getAcl().getExtensions());
172
173 if (objectData.isExactAcl() != null) {
174 final Acl objectAcl = objectData.getAcl();
175 final Boolean isExact = objectData.isExactAcl();
176 acl = new Acl() {
177
178 @Override
179 public void setExtensions(List<CmisExtensionElement> extensions) {
180 objectAcl.setExtensions(extensions);
181 }
182
183 @Override
184 public List<CmisExtensionElement> getExtensions() {
185 return objectAcl.getExtensions();
186 }
187
188 @Override
189 public Boolean isExact() {
190 return isExact;
191 }
192
193 @Override
194 public List<Ace> getAces() {
195 return objectAcl.getAces();
196 }
197 };
198 }
199 } else {
200 acl = null;
201 }
202
203
204 if (objectData.getPolicyIds() != null && objectData.getPolicyIds().getPolicyIds() != null) {
205 if (objectData.getPolicyIds().getPolicyIds().isEmpty()) {
206 policies = null;
207 } else {
208 policies = new ArrayList<Policy>();
209 for (String pid : objectData.getPolicyIds().getPolicyIds()) {
210 CmisObject policy = session.getObject(pid);
211 if (policy instanceof Policy) {
212 policies.add((Policy) policy);
213 }
214 }
215 }
216 extensions.put(ExtensionLevel.POLICIES, objectData.getPolicyIds().getExtensions());
217 } else {
218 policies = null;
219 }
220
221
222 if (objectData.getRelationships() != null && !objectData.getRelationships().isEmpty()) {
223 relationships = new ArrayList<Relationship>();
224 for (ObjectData rod : objectData.getRelationships()) {
225 CmisObject relationship = of.convertObject(rod, this.creationContext);
226 if (relationship instanceof Relationship) {
227 relationships.add((Relationship) relationship);
228 }
229 }
230 } else {
231 relationships = null;
232 }
233
234 extensions.put(ExtensionLevel.OBJECT, objectData.getExtensions());
235 }
236
237
238
239
240 protected void writeLock() {
241 lock.writeLock().lock();
242 }
243
244
245
246
247 protected void writeUnlock() {
248 lock.writeLock().unlock();
249 }
250
251
252
253
254 protected void readLock() {
255 lock.readLock().lock();
256 }
257
258
259
260
261 protected void readUnlock() {
262 lock.readLock().unlock();
263 }
264
265
266
267
268 protected SessionImpl getSession() {
269 return session;
270 }
271
272
273
274
275 protected String getRepositoryId() {
276 return getSession().getRepositoryId();
277 }
278
279
280
281
282 protected ObjectType getObjectType() {
283 readLock();
284 try {
285 return objectType;
286 } finally {
287 readUnlock();
288 }
289 }
290
291
292
293
294 protected CmisBinding getBinding() {
295 return getSession().getBinding();
296 }
297
298
299
300
301 protected ObjectFactory getObjectFactory() {
302 return getSession().getObjectFactory();
303 }
304
305
306
307
308
309 protected String getObjectId() {
310 String objectId = getId();
311 if (objectId == null) {
312 throw new IllegalStateException("Object Id is unknown!");
313 }
314
315 return objectId;
316 }
317
318
319
320
321 protected OperationContext getCreationContext() {
322 return creationContext;
323 }
324
325
326
327
328 protected String getPropertyQueryName(String propertyId) {
329 readLock();
330 try {
331 PropertyDefinition<?> propDef = objectType.getPropertyDefinitions().get(propertyId);
332 if (propDef == null) {
333 return null;
334 }
335
336 return propDef.getQueryName();
337 } finally {
338 readUnlock();
339 }
340 }
341
342
343
344 @Override
345 public void delete() {
346 delete(true);
347 }
348
349 @Override
350 public void delete(boolean allVersions) {
351 readLock();
352 try {
353 getSession().delete(this, allVersions);
354 } finally {
355 readUnlock();
356 }
357 }
358
359
360
361 @Override
362 public CmisObject updateProperties(Map<String, ?> properties) {
363 ObjectId objectId = updateProperties(properties, true);
364 if (objectId == null) {
365 return null;
366 }
367
368 if (!getObjectId().equals(objectId.getId())) {
369 return getSession().getObject(objectId, getCreationContext());
370 }
371
372 return this;
373 }
374
375 @Override
376 public ObjectId updateProperties(Map<String, ?> properties, boolean refresh) {
377 if (isNullOrEmpty(properties)) {
378 throw new IllegalArgumentException("Properties must not be empty!");
379 }
380
381 readLock();
382 String newObjectId = null;
383 try {
384 String objectId = getObjectId();
385 Holder<String> objectIdHolder = new Holder<String>(objectId);
386
387 String changeToken = getChangeToken();
388 Holder<String> changeTokenHolder = new Holder<String>(changeToken);
389
390 Set<Updatability> updatebility = EnumSet.noneOf(Updatability.class);
391 updatebility.add(Updatability.READWRITE);
392
393
394 Boolean isCheckedOut = getPropertyValue(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT);
395 if (Boolean.TRUE.equals(isCheckedOut)) {
396 updatebility.add(Updatability.WHENCHECKEDOUT);
397 }
398
399
400 getBinding().getObjectService().updateProperties(
401 getRepositoryId(),
402 objectIdHolder,
403 changeTokenHolder,
404 getObjectFactory()
405 .convertProperties(properties, this.objectType, this.secondaryTypes, updatebility), null);
406
407 newObjectId = objectIdHolder.getValue();
408
409
410 getSession().removeObjectFromCache(objectId);
411 } finally {
412 readUnlock();
413 }
414
415 if (refresh) {
416 refresh();
417 }
418
419 if (newObjectId == null) {
420 return null;
421 }
422
423 return getSession().createObjectId(newObjectId);
424 }
425
426 @Override
427 public CmisObject updateProperties(Map<String, ?> properties, List<String> addSecondaryTypeIds,
428 List<String> removeSecondaryTypeIds) {
429 ObjectId objectId = updateProperties(properties, addSecondaryTypeIds, removeSecondaryTypeIds, true);
430 if (objectId == null) {
431 return null;
432 }
433
434 if (!getObjectId().equals(objectId.getId())) {
435 return getSession().getObject(objectId, getCreationContext());
436 }
437
438 return this;
439 }
440
441 @Override
442 public ObjectId updateProperties(Map<String, ?> properties, List<String> addSecondaryTypeIds,
443 List<String> removeSecondaryTypeIds, boolean refresh) {
444 if ((addSecondaryTypeIds == null || addSecondaryTypeIds.isEmpty())
445 && (removeSecondaryTypeIds == null || removeSecondaryTypeIds.isEmpty())) {
446 return updateProperties(properties, refresh);
447 }
448
449 List<String> secondaryTypeIds = new ArrayList<String>();
450
451 readLock();
452 try {
453
454 if (!this.properties.containsKey(PropertyIds.SECONDARY_OBJECT_TYPE_IDS)) {
455 throw new IllegalStateException("Secondary Object Type Ids are not available!");
456 }
457
458
459 if (secondaryTypes != null) {
460 for (SecondaryType type : secondaryTypes) {
461 if (removeSecondaryTypeIds == null || !removeSecondaryTypeIds.contains(type.getId())) {
462 secondaryTypeIds.add(type.getId());
463 }
464 }
465 }
466
467 if (addSecondaryTypeIds != null) {
468 for (String addId : addSecondaryTypeIds) {
469 if (!secondaryTypeIds.contains(addId)) {
470 secondaryTypeIds.add(addId);
471 }
472 }
473 }
474 } finally {
475 readUnlock();
476 }
477
478
479 Map<String, Object> newProperties = new HashMap<String, Object>();
480 if (properties != null) {
481 newProperties.putAll(properties);
482 }
483 newProperties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryTypeIds);
484
485 return updateProperties(newProperties, refresh);
486 }
487
488 @Override
489 public CmisObject rename(String newName) {
490 if (newName == null || newName.length() == 0) {
491 throw new IllegalArgumentException("New name must not be empty!");
492 }
493
494 Map<String, Object> prop = new HashMap<String, Object>();
495 prop.put(PropertyIds.NAME, newName);
496
497 return updateProperties(prop);
498 }
499
500 @Override
501 public ObjectId rename(String newName, boolean refresh) {
502 if (newName == null || newName.length() == 0) {
503 throw new IllegalArgumentException("New name must not be empty!");
504 }
505
506 Map<String, Object> prop = new HashMap<String, Object>();
507 prop.put(PropertyIds.NAME, newName);
508
509 return updateProperties(prop, refresh);
510 }
511
512
513
514 @Override
515 public ObjectType getBaseType() {
516 BaseTypeId baseTypeId = getBaseTypeId();
517 if (baseTypeId == null) {
518 return null;
519 }
520
521 return getSession().getTypeDefinition(baseTypeId.value());
522 }
523
524 @Override
525 public BaseTypeId getBaseTypeId() {
526 String baseType = getPropertyValue(PropertyIds.BASE_TYPE_ID);
527 if (baseType == null) {
528 return null;
529 }
530
531 return BaseTypeId.fromValue(baseType);
532 }
533
534 @Override
535 public String getChangeToken() {
536 return getPropertyValue(PropertyIds.CHANGE_TOKEN);
537 }
538
539 @Override
540 public String getCreatedBy() {
541 return getPropertyValue(PropertyIds.CREATED_BY);
542 }
543
544 @Override
545 public GregorianCalendar getCreationDate() {
546 return getPropertyValue(PropertyIds.CREATION_DATE);
547 }
548
549 @Override
550 public String getId() {
551 return getPropertyValue(PropertyIds.OBJECT_ID);
552 }
553
554 @Override
555 public GregorianCalendar getLastModificationDate() {
556 return getPropertyValue(PropertyIds.LAST_MODIFICATION_DATE);
557 }
558
559 @Override
560 public String getLastModifiedBy() {
561 return getPropertyValue(PropertyIds.LAST_MODIFIED_BY);
562 }
563
564 @Override
565 public String getName() {
566 return getPropertyValue(PropertyIds.NAME);
567 }
568
569 @Override
570 public String getDescription() {
571 return getPropertyValue(PropertyIds.DESCRIPTION);
572 }
573
574 @Override
575 public List<Property<?>> getProperties() {
576 readLock();
577 try {
578 return Collections.unmodifiableList(new ArrayList<Property<?>>(properties.values()));
579 } finally {
580 readUnlock();
581 }
582 }
583
584 @Override
585 @SuppressWarnings("unchecked")
586 public <T> Property<T> getProperty(String id) {
587 readLock();
588 try {
589 return (Property<T>) properties.get(id);
590 } finally {
591 readUnlock();
592 }
593 }
594
595 @Override
596 @SuppressWarnings("unchecked")
597 public <T> T getPropertyValue(String id) {
598 Property<T> property = getProperty(id);
599 if (property == null) {
600 return null;
601 }
602
603 return (T) property.getValue();
604 }
605
606 @Override
607 public ObjectType getType() {
608 readLock();
609 try {
610 return this.objectType;
611 } finally {
612 readUnlock();
613 }
614 }
615
616 @Override
617 public List<SecondaryType> getSecondaryTypes() {
618 readLock();
619 try {
620 return secondaryTypes;
621 } finally {
622 readUnlock();
623 }
624 }
625
626 @Override
627 public List<ObjectType> findObjectType(String id) {
628 List<ObjectType> result = null;
629
630 readLock();
631 try {
632 if (objectType.getPropertyDefinitions().containsKey(id)) {
633 result = new ArrayList<ObjectType>();
634 result.add(objectType);
635 }
636
637 if (secondaryTypes != null) {
638 for (SecondaryType secondaryType : secondaryTypes) {
639 if (secondaryType.getPropertyDefinitions() != null
640 && secondaryType.getPropertyDefinitions().containsKey(id)) {
641 if (result == null) {
642 result = new ArrayList<ObjectType>();
643 }
644 result.add(secondaryType);
645 }
646 }
647 }
648 } finally {
649 readUnlock();
650 }
651
652 return result;
653 }
654
655
656
657 @Override
658 public AllowableActions getAllowableActions() {
659 readLock();
660 try {
661 return this.allowableActions;
662 } finally {
663 readUnlock();
664 }
665 }
666
667 @Override
668 public boolean hasAllowableAction(Action action) {
669 if (action == null) {
670 throw new IllegalArgumentException("Action must be set!");
671 }
672
673 AllowableActions currentAllowableActions = getAllowableActions();
674 if (currentAllowableActions == null || currentAllowableActions.getAllowableActions() == null) {
675 throw new IllegalStateException("Allowable Actions are not available!");
676 }
677
678 return currentAllowableActions.getAllowableActions().contains(action);
679 }
680
681
682
683 @Override
684 public List<Rendition> getRenditions() {
685 readLock();
686 try {
687 return this.renditions;
688 } finally {
689 readUnlock();
690 }
691 }
692
693
694
695 public Acl getAcl(boolean onlyBasicPermissions) {
696 String objectId = getObjectId();
697 return getBinding().getAclService().getAcl(getRepositoryId(), objectId, onlyBasicPermissions, null);
698 }
699
700 @Override
701 public Acl applyAcl(List<Ace> addAces, List<Ace> removeAces, AclPropagation aclPropagation) {
702 Acl result = getSession().applyAcl(this, addAces, removeAces, aclPropagation);
703
704 refresh();
705
706 return result;
707 }
708
709 @Override
710 public Acl addAcl(List<Ace> addAces, AclPropagation aclPropagation) {
711 return applyAcl(addAces, null, aclPropagation);
712 }
713
714 @Override
715 public Acl removeAcl(List<Ace> removeAces, AclPropagation aclPropagation) {
716 return applyAcl(null, removeAces, aclPropagation);
717 }
718
719 @Override
720 public Acl setAcl(List<Ace> aces) {
721 Acl result = getSession().setAcl(this, aces);
722
723 refresh();
724
725 return result;
726 }
727
728 @Override
729 public Acl getAcl() {
730 readLock();
731 try {
732 return acl;
733 } finally {
734 readUnlock();
735 }
736 }
737
738 @Override
739 public Set<String> getPermissionsForPrincipal(String principalId) {
740 if (principalId == null) {
741 throw new IllegalArgumentException("Principal must be set!");
742 }
743
744 Acl currentAcl = getAcl();
745
746 if (currentAcl == null) {
747 throw new IllegalStateException("ACLs are not available!");
748 }
749
750 if (isNullOrEmpty(acl.getAces())) {
751 return Collections.emptySet();
752 }
753
754 HashSet<String> result = new HashSet<String>();
755
756 for (Ace ace : acl.getAces()) {
757 if (principalId.equals(ace.getPrincipalId()) && ace.getPermissions() != null) {
758 result.addAll(ace.getPermissions());
759 }
760 }
761
762 return result;
763 }
764
765
766
767 @Override
768 public void applyPolicy(ObjectId... policyIds) {
769 readLock();
770 try {
771 getSession().applyPolicy(this, policyIds);
772 } finally {
773 readUnlock();
774 }
775
776 refresh();
777 }
778
779 @Override
780 public void applyPolicy(ObjectId policyId, boolean refresh) {
781 readLock();
782 try {
783 getSession().applyPolicy(this, policyId);
784 } finally {
785 readUnlock();
786 }
787
788 if (refresh) {
789 refresh();
790 }
791 }
792
793 @Override
794 public void removePolicy(ObjectId... policyIds) {
795 readLock();
796 try {
797 getSession().removePolicy(this, policyIds);
798 } finally {
799 readUnlock();
800 }
801
802 refresh();
803 }
804
805 @Override
806 public void removePolicy(ObjectId policyId, boolean refresh) {
807 readLock();
808 try {
809 getSession().removePolicy(this, policyId);
810 } finally {
811 readUnlock();
812 }
813
814 if (refresh) {
815 refresh();
816 }
817 }
818
819 @Override
820 public List<Policy> getPolicies() {
821 readLock();
822 try {
823 return policies;
824 } finally {
825 readUnlock();
826 }
827 }
828
829
830
831 @Override
832 public List<Relationship> getRelationships() {
833 readLock();
834 try {
835 return this.relationships;
836 } finally {
837 readUnlock();
838 }
839 }
840
841
842
843 @Override
844 public List<CmisExtensionElement> getExtensions(ExtensionLevel level) {
845 List<CmisExtensionElement> ext = extensions.get(level);
846 if (ext == null) {
847 return null;
848 }
849
850 return Collections.unmodifiableList(ext);
851 }
852
853
854
855 @Override
856 public <T> T getAdapter(Class<T> adapterInterface) {
857 return null;
858 }
859
860
861
862 @Override
863 public long getRefreshTimestamp() {
864 readLock();
865 try {
866 return this.refreshTimestamp;
867 } finally {
868 readUnlock();
869 }
870 }
871
872 @Override
873 public void refresh() {
874 writeLock();
875 try {
876 String objectId = getObjectId();
877
878 OperationContext oc = getCreationContext();
879
880
881 ObjectData objectData = getSession()
882 .getBinding()
883 .getObjectService()
884 .getObject(getRepositoryId(), objectId, oc.getFilterString(), oc.isIncludeAllowableActions(),
885 oc.getIncludeRelationships(), oc.getRenditionFilterString(), oc.isIncludePolicies(),
886 oc.isIncludeAcls(), null);
887
888
889 initialize(session, session.getTypeDefinition(objectType.getId()), objectData, creationContext);
890 } finally {
891 writeUnlock();
892 }
893 }
894
895 @Override
896 public void refreshIfOld(long durationInMillis) {
897 writeLock();
898 try {
899 if (this.refreshTimestamp < System.currentTimeMillis() - durationInMillis) {
900 refresh();
901 }
902 } finally {
903 writeUnlock();
904 }
905 }
906
907 @Override
908 public String toString() {
909 readLock();
910 try {
911 if (objectType == null) {
912 return "<unknown>";
913 }
914
915 return objectType.getBaseTypeId() + " (" + objectType.getId() + "): " + getId();
916 } finally {
917 readUnlock();
918 }
919 }
920 }