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.repository;
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.InputStream;
25 import java.io.Serializable;
26 import java.math.BigDecimal;
27 import java.math.BigInteger;
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.Date;
32 import java.util.GregorianCalendar;
33 import java.util.HashMap;
34 import java.util.LinkedHashMap;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Set;
38
39 import org.apache.chemistry.opencmis.client.api.ChangeEvent;
40 import org.apache.chemistry.opencmis.client.api.ChangeEvents;
41 import org.apache.chemistry.opencmis.client.api.CmisObject;
42 import org.apache.chemistry.opencmis.client.api.ObjectFactory;
43 import org.apache.chemistry.opencmis.client.api.ObjectType;
44 import org.apache.chemistry.opencmis.client.api.OperationContext;
45 import org.apache.chemistry.opencmis.client.api.Policy;
46 import org.apache.chemistry.opencmis.client.api.Property;
47 import org.apache.chemistry.opencmis.client.api.QueryResult;
48 import org.apache.chemistry.opencmis.client.api.Rendition;
49 import org.apache.chemistry.opencmis.client.api.SecondaryType;
50 import org.apache.chemistry.opencmis.client.api.Session;
51 import org.apache.chemistry.opencmis.client.runtime.ChangeEventImpl;
52 import org.apache.chemistry.opencmis.client.runtime.ChangeEventsImpl;
53 import org.apache.chemistry.opencmis.client.runtime.DocumentImpl;
54 import org.apache.chemistry.opencmis.client.runtime.FolderImpl;
55 import org.apache.chemistry.opencmis.client.runtime.ItemImpl;
56 import org.apache.chemistry.opencmis.client.runtime.PolicyImpl;
57 import org.apache.chemistry.opencmis.client.runtime.PropertyImpl;
58 import org.apache.chemistry.opencmis.client.runtime.QueryResultImpl;
59 import org.apache.chemistry.opencmis.client.runtime.RelationshipImpl;
60 import org.apache.chemistry.opencmis.client.runtime.RenditionImpl;
61 import org.apache.chemistry.opencmis.client.runtime.SessionImpl;
62 import org.apache.chemistry.opencmis.client.runtime.objecttype.DocumentTypeImpl;
63 import org.apache.chemistry.opencmis.client.runtime.objecttype.FolderTypeImpl;
64 import org.apache.chemistry.opencmis.client.runtime.objecttype.ItemTypeImpl;
65 import org.apache.chemistry.opencmis.client.runtime.objecttype.PolicyTypeImpl;
66 import org.apache.chemistry.opencmis.client.runtime.objecttype.RelationshipTypeImpl;
67 import org.apache.chemistry.opencmis.client.runtime.objecttype.SecondaryTypeImpl;
68 import org.apache.chemistry.opencmis.commons.PropertyIds;
69 import org.apache.chemistry.opencmis.commons.data.Ace;
70 import org.apache.chemistry.opencmis.commons.data.Acl;
71 import org.apache.chemistry.opencmis.commons.data.ContentStream;
72 import org.apache.chemistry.opencmis.commons.data.ObjectData;
73 import org.apache.chemistry.opencmis.commons.data.ObjectList;
74 import org.apache.chemistry.opencmis.commons.data.Properties;
75 import org.apache.chemistry.opencmis.commons.data.PropertyData;
76 import org.apache.chemistry.opencmis.commons.data.PropertyId;
77 import org.apache.chemistry.opencmis.commons.data.RenditionData;
78 import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
79 import org.apache.chemistry.opencmis.commons.definitions.DocumentTypeDefinition;
80 import org.apache.chemistry.opencmis.commons.definitions.FolderTypeDefinition;
81 import org.apache.chemistry.opencmis.commons.definitions.ItemTypeDefinition;
82 import org.apache.chemistry.opencmis.commons.definitions.PolicyTypeDefinition;
83 import org.apache.chemistry.opencmis.commons.definitions.PropertyBooleanDefinition;
84 import org.apache.chemistry.opencmis.commons.definitions.PropertyDateTimeDefinition;
85 import org.apache.chemistry.opencmis.commons.definitions.PropertyDecimalDefinition;
86 import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
87 import org.apache.chemistry.opencmis.commons.definitions.PropertyHtmlDefinition;
88 import org.apache.chemistry.opencmis.commons.definitions.PropertyIdDefinition;
89 import org.apache.chemistry.opencmis.commons.definitions.PropertyIntegerDefinition;
90 import org.apache.chemistry.opencmis.commons.definitions.PropertyStringDefinition;
91 import org.apache.chemistry.opencmis.commons.definitions.PropertyUriDefinition;
92 import org.apache.chemistry.opencmis.commons.definitions.RelationshipTypeDefinition;
93 import org.apache.chemistry.opencmis.commons.definitions.SecondaryTypeDefinition;
94 import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
95 import org.apache.chemistry.opencmis.commons.enums.Cardinality;
96 import org.apache.chemistry.opencmis.commons.enums.ChangeType;
97 import org.apache.chemistry.opencmis.commons.enums.Updatability;
98 import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
99 import org.apache.chemistry.opencmis.commons.impl.DateTimeHelper;
100 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl;
101 import org.apache.chemistry.opencmis.commons.impl.dataobjects.PartialContentStreamImpl;
102 import org.apache.chemistry.opencmis.commons.spi.BindingsObjectFactory;
103
104
105
106
107 public class ObjectFactoryImpl implements ObjectFactory, Serializable {
108
109 private static final long serialVersionUID = 1L;
110
111 private Session session;
112
113
114
115
116 public ObjectFactoryImpl() {
117 }
118
119 @Override
120 public void initialize(Session session, Map<String, String> parameters) {
121 assert session != null;
122
123 this.session = session;
124 }
125
126
127
128
129 protected BindingsObjectFactory getBindingsObjectFactory() {
130 return session.getBinding().getObjectFactory();
131 }
132
133
134
135 @Override
136 public RepositoryInfo convertRepositoryInfo(RepositoryInfo repositoryInfo) {
137 return repositoryInfo;
138 }
139
140
141
142 @Override
143 public Acl convertAces(List<Ace> aces) {
144 if (aces == null) {
145 return null;
146 }
147
148 BindingsObjectFactory bof = getBindingsObjectFactory();
149
150 List<Ace> bindingAces = new ArrayList<Ace>();
151 for (Ace ace : aces) {
152 bindingAces.add(bof.createAccessControlEntry(ace.getPrincipalId(), ace.getPermissions()));
153 }
154
155 return bof.createAccessControlList(bindingAces);
156 }
157
158 @Override
159 public Ace createAce(String principal, List<String> permissions) {
160 BindingsObjectFactory bof = getBindingsObjectFactory();
161
162 Ace ace = bof.createAccessControlEntry(principal, permissions);
163
164 return ace;
165 }
166
167 @Override
168 public Acl createAcl(List<Ace> aces) {
169 BindingsObjectFactory bof = getBindingsObjectFactory();
170
171 Acl acl = bof.createAccessControlList(aces);
172
173 return acl;
174 }
175
176
177
178 @Override
179 public List<String> convertPolicies(List<Policy> policies) {
180 if (policies == null) {
181 return null;
182 }
183
184 List<String> result = new ArrayList<String>();
185
186 for (Policy policy : policies) {
187 if ((policy != null) && (policy.getId() != null)) {
188 result.add(policy.getId());
189 }
190 }
191
192 return result;
193 }
194
195
196
197 @Override
198 public Rendition convertRendition(String objectId, RenditionData rendition) {
199 if (rendition == null) {
200 throw new IllegalArgumentException("Rendition must be set!");
201 }
202
203 long length = (rendition.getBigLength() == null ? -1 : rendition.getBigLength().longValue());
204 int height = (rendition.getBigHeight() == null ? -1 : rendition.getBigHeight().intValue());
205 int width = (rendition.getBigWidth() == null ? -1 : rendition.getBigWidth().intValue());
206
207 return new RenditionImpl(this.session, objectId, rendition.getStreamId(), rendition.getRenditionDocumentId(),
208 rendition.getKind(), length, rendition.getMimeType(), rendition.getTitle(), height, width);
209 }
210
211
212
213 @Override
214 public ContentStream createContentStream(String filename, long length, String mimetype, InputStream stream) {
215 return createContentStream(filename, length, mimetype, stream, false);
216 }
217
218 @Override
219 public ContentStream createContentStream(String filename, long length, String mimetype, InputStream stream,
220 boolean partial) {
221 if (partial) {
222 return new PartialContentStreamImpl(filename, (length < 0 ? null : BigInteger.valueOf(length)), mimetype,
223 stream);
224 } else {
225 return new ContentStreamImpl(filename, (length < 0 ? null : BigInteger.valueOf(length)), mimetype, stream);
226 }
227 }
228
229 @Override
230 public ContentStream convertContentStream(ContentStream contentStream) {
231 if (contentStream == null) {
232 return null;
233 }
234
235 BigInteger length = (contentStream.getLength() < 0 ? null : BigInteger.valueOf(contentStream.getLength()));
236
237 return getBindingsObjectFactory().createContentStream(contentStream.getFileName(), length,
238 contentStream.getMimeType(), contentStream.getStream());
239 }
240
241
242
243 @Override
244 public ObjectType convertTypeDefinition(TypeDefinition typeDefinition) {
245 if (typeDefinition instanceof DocumentTypeDefinition) {
246 return new DocumentTypeImpl(this.session, (DocumentTypeDefinition) typeDefinition);
247 } else if (typeDefinition instanceof FolderTypeDefinition) {
248 return new FolderTypeImpl(this.session, (FolderTypeDefinition) typeDefinition);
249 } else if (typeDefinition instanceof RelationshipTypeDefinition) {
250 return new RelationshipTypeImpl(this.session, (RelationshipTypeDefinition) typeDefinition);
251 } else if (typeDefinition instanceof PolicyTypeDefinition) {
252 return new PolicyTypeImpl(this.session, (PolicyTypeDefinition) typeDefinition);
253 } else if (typeDefinition instanceof ItemTypeDefinition) {
254 return new ItemTypeImpl(this.session, (ItemTypeDefinition) typeDefinition);
255 } else if (typeDefinition instanceof SecondaryTypeDefinition) {
256 return new SecondaryTypeImpl(this.session, (SecondaryTypeDefinition) typeDefinition);
257 } else if (typeDefinition == null) {
258 throw new CmisRuntimeException("No base type supplied!");
259 } else {
260 throw new CmisRuntimeException("Unknown base type! Received " + typeDefinition.getClass().getName());
261 }
262 }
263
264 @Override
265 public ObjectType getTypeFromObjectData(ObjectData objectData) {
266 if (objectData == null || objectData.getProperties() == null
267 || objectData.getProperties().getProperties() == null) {
268 return null;
269 }
270
271 PropertyData<?> typeProperty = objectData.getProperties().getProperties().get(PropertyIds.OBJECT_TYPE_ID);
272 if (!(typeProperty instanceof PropertyId)) {
273 return null;
274 }
275
276 return this.session.getTypeDefinition((String) typeProperty.getFirstValue());
277 }
278
279
280
281 @Override
282 public <T> Property<T> createProperty(PropertyDefinition<T> type, List<T> values) {
283 return new PropertyImpl<T>(type, values);
284 }
285
286 @SuppressWarnings("unchecked")
287 protected <T> Property<T> convertProperty(ObjectType objectType, Collection<SecondaryType> secondaryTypes,
288 PropertyData<T> pd) {
289
290
291 if (pd.getId() == null || pd.getId().length() == 0) {
292 StringBuilder sb = null;
293 if (isNotEmpty(secondaryTypes)) {
294 sb = new StringBuilder(128);
295 sb.append(" or a secondary type of the object (");
296 addSecondaryTypeIds(secondaryTypes, sb);
297 sb.append(')');
298 }
299
300 throw new CmisRuntimeException(
301 "Cannot convert a property because it has no ID! The property is supposed to be part of the type '"
302 + objectType.getId() + "'" + (sb == null ? "" : sb.toString())
303 + ". The value of this property is: " + pd.getValues());
304 }
305
306 PropertyDefinition<T> definition = (PropertyDefinition<T>) objectType.getPropertyDefinitions().get(pd.getId());
307
308
309 if (definition == null && secondaryTypes != null) {
310 for (SecondaryType secondaryType : secondaryTypes) {
311 if (secondaryType != null && secondaryType.getPropertyDefinitions() != null) {
312 definition = (PropertyDefinition<T>) secondaryType.getPropertyDefinitions().get(pd.getId());
313 if (definition != null) {
314 break;
315 }
316 }
317 }
318 }
319
320
321 if (definition == null) {
322 TypeDefinition reloadedObjectType = session.getTypeDefinition(objectType.getId(), false);
323 definition = (PropertyDefinition<T>) reloadedObjectType.getPropertyDefinitions().get(pd.getId());
324
325 if (definition == null && secondaryTypes != null) {
326 for (SecondaryType secondaryType : secondaryTypes) {
327 if (secondaryType != null) {
328 TypeDefinition reloadedSecondaryType = session.getTypeDefinition(secondaryType.getId(), false);
329 if (reloadedSecondaryType.getPropertyDefinitions() != null) {
330 definition = (PropertyDefinition<T>) reloadedSecondaryType.getPropertyDefinitions().get(
331 pd.getId());
332 if (definition != null) {
333 break;
334 }
335 }
336 }
337 }
338 }
339 }
340
341 if (definition == null) {
342
343
344 StringBuilder sb = null;
345 if (isNotEmpty(secondaryTypes)) {
346 sb = new StringBuilder(128);
347 sb.append(" or any secondary type of the object (");
348 addSecondaryTypeIds(secondaryTypes, sb);
349 sb.append(')');
350 }
351
352 throw new CmisRuntimeException(
353 "Cannot convert property '"
354 + pd.getId()
355 + "' because it does not exist in the object type. The property is supposed to be part of the type '"
356 + objectType.getId() + "'" + (sb == null ? "" : sb.toString())
357 + ". The value of this property is: " + pd.getValues());
358 }
359
360 return createProperty(definition, pd.getValues());
361 }
362
363 private void addSecondaryTypeIds(Collection<SecondaryType> secondaryTypes, StringBuilder sb) {
364 boolean first = true;
365 for (SecondaryType secondaryType : secondaryTypes) {
366 if (first) {
367 first = false;
368 } else {
369 sb.append(", ");
370 }
371
372 sb.append('\'');
373 sb.append(secondaryType.getId());
374 sb.append('\'');
375 }
376 }
377
378 @Override
379 public Map<String, Property<?>> convertProperties(ObjectType objectType, Collection<SecondaryType> secondaryTypes,
380 Properties properties) {
381
382 if (objectType == null) {
383 throw new IllegalArgumentException("Object type must set!");
384 }
385
386 if (objectType.getPropertyDefinitions() == null) {
387 throw new IllegalArgumentException("Object type has no property defintions!");
388 }
389
390 if (properties == null || properties.getProperties() == null) {
391 throw new IllegalArgumentException("Properties must be set!");
392 }
393
394
395 Map<String, Property<?>> result = new LinkedHashMap<String, Property<?>>();
396 for (Map.Entry<String, PropertyData<?>> entry : properties.getProperties().entrySet()) {
397
398 Property<?> apiProperty = convertProperty(objectType, secondaryTypes, entry.getValue());
399 result.put(entry.getKey(), apiProperty);
400 }
401
402 return result;
403 }
404
405 @Override
406 @SuppressWarnings({ "unchecked", "rawtypes" })
407 public Properties convertProperties(Map<String, ?> properties, ObjectType type,
408 Collection<SecondaryType> secondaryTypes, Set<Updatability> updatabilityFilter) {
409
410 if (properties == null) {
411 return null;
412 }
413
414
415 if (type == null) {
416 Object typeId = properties.get(PropertyIds.OBJECT_TYPE_ID);
417
418 if (typeId instanceof String) {
419 type = session.getTypeDefinition(typeId.toString());
420 } else if (typeId instanceof List && !((List) typeId).isEmpty() && ((List) typeId).get(0) instanceof String) {
421 type = session.getTypeDefinition(((List) typeId).get(0).toString());
422 } else {
423 throw new IllegalArgumentException("Type or type property must be set!");
424 }
425 }
426
427
428 Collection<SecondaryType> allSecondaryTypes = null;
429 Object secondaryTypeIds = properties.get(PropertyIds.SECONDARY_OBJECT_TYPE_IDS);
430 if (secondaryTypeIds instanceof List) {
431 allSecondaryTypes = new ArrayList<SecondaryType>();
432
433 for (Object secondaryTypeId : (List<?>) secondaryTypeIds) {
434 if (!(secondaryTypeId instanceof String)) {
435 throw new IllegalArgumentException("Secondary types property contains an invalid entry: "
436 + secondaryTypeId);
437 }
438
439 ObjectType secondaryType = session.getTypeDefinition(secondaryTypeId.toString());
440 if (!(secondaryType instanceof SecondaryType)) {
441 throw new IllegalArgumentException(
442 "Secondary types property contains a type that is not a secondary type: " + secondaryTypeId);
443 }
444
445 allSecondaryTypes.add((SecondaryType) secondaryType);
446 }
447 }
448
449 if (secondaryTypes != null && allSecondaryTypes == null) {
450 allSecondaryTypes = secondaryTypes;
451 }
452
453
454 BindingsObjectFactory bof = getBindingsObjectFactory();
455 List<PropertyData<?>> propertyList = new ArrayList<PropertyData<?>>();
456
457
458 for (Map.Entry<String, ?> property : properties.entrySet()) {
459 if ((property == null) || (property.getKey() == null)) {
460 continue;
461 }
462
463 String id = property.getKey();
464 Object value = property.getValue();
465
466 if (value instanceof Property<?>) {
467 Property<?> p = (Property<?>) value;
468 if (!id.equals(p.getId())) {
469 throw new IllegalArgumentException("Property id mismatch: '" + id + "' != '" + p.getId() + "'!");
470 }
471 value = (p.getDefinition().getCardinality() == Cardinality.SINGLE ? p.getFirstValue() : p.getValues());
472 }
473
474
475 PropertyDefinition<?> definition = type.getPropertyDefinitions().get(id);
476
477 if (definition == null && allSecondaryTypes != null) {
478 for (SecondaryType secondaryType : allSecondaryTypes) {
479 if (secondaryType != null && secondaryType.getPropertyDefinitions() != null) {
480 definition = secondaryType.getPropertyDefinitions().get(id);
481 if (definition != null) {
482 break;
483 }
484 }
485 }
486 }
487
488 if (definition == null) {
489 throw new IllegalArgumentException("Property '" + id
490 + "' is not valid for this type or one of the secondary types!");
491 }
492
493
494 if (updatabilityFilter != null) {
495 if (!updatabilityFilter.contains(definition.getUpdatability())) {
496 continue;
497 }
498 }
499
500
501 List<?> values;
502 if (value == null) {
503 values = null;
504 } else if (value instanceof List<?>) {
505 if (definition.getCardinality() != Cardinality.MULTI) {
506 throw new IllegalArgumentException("Property '" + id + "' is not a multi value property!");
507 }
508 values = (List<?>) value;
509
510
511
512 Class<?> valueClazz = null;
513 for (Object o : values) {
514 if (o == null) {
515 throw new IllegalArgumentException("Property '" + id + "' contains null values!");
516 }
517 if (valueClazz == null) {
518 valueClazz = o.getClass();
519 } else {
520 if (!valueClazz.isInstance(o)) {
521 throw new IllegalArgumentException("Property '" + id + "' is inhomogeneous!");
522 }
523 }
524 }
525 } else {
526 if (definition.getCardinality() != Cardinality.SINGLE) {
527 throw new IllegalArgumentException("Property '" + id + "' is not a single value property!");
528 }
529 values = Collections.singletonList(value);
530 }
531
532
533 PropertyData<?> propertyData = null;
534 Object firstValue = (isNullOrEmpty(values) ? null : values.get(0));
535
536 if (definition instanceof PropertyStringDefinition) {
537 if (firstValue == null) {
538 propertyData = bof.createPropertyStringData(id, (List<String>) null);
539 } else if (firstValue instanceof String) {
540 propertyData = bof.createPropertyStringData(id, (List<String>) values);
541 } else {
542 throwWrongTypeError(firstValue, "string", String.class, id);
543 }
544 } else if (definition instanceof PropertyIdDefinition) {
545 if (firstValue == null) {
546 propertyData = bof.createPropertyIdData(id, (List<String>) null);
547 } else if (firstValue instanceof String) {
548 propertyData = bof.createPropertyIdData(id, (List<String>) values);
549 } else {
550 throwWrongTypeError(firstValue, "string", String.class, id);
551 }
552 } else if (definition instanceof PropertyHtmlDefinition) {
553 if (firstValue == null) {
554 propertyData = bof.createPropertyHtmlData(id, (List<String>) values);
555 } else if (firstValue instanceof String) {
556 propertyData = bof.createPropertyHtmlData(id, (List<String>) values);
557 } else {
558 throwWrongTypeError(firstValue, "html", String.class, id);
559 }
560 } else if (definition instanceof PropertyUriDefinition) {
561 if (firstValue == null) {
562 propertyData = bof.createPropertyUriData(id, (List<String>) null);
563 } else if (firstValue instanceof String) {
564 propertyData = bof.createPropertyUriData(id, (List<String>) values);
565 } else {
566 throwWrongTypeError(firstValue, "uri", String.class, id);
567 }
568 } else if (definition instanceof PropertyIntegerDefinition) {
569 if (firstValue == null) {
570 propertyData = bof.createPropertyIntegerData(id, (List<BigInteger>) null);
571 } else if (firstValue instanceof BigInteger) {
572 propertyData = bof.createPropertyIntegerData(id, (List<BigInteger>) values);
573 } else if ((firstValue instanceof Byte) || (firstValue instanceof Short)
574 || (firstValue instanceof Integer) || (firstValue instanceof Long)) {
575
576 List<BigInteger> list = new ArrayList<BigInteger>(values.size());
577 for (Object v : values) {
578 list.add(BigInteger.valueOf(((Number) v).longValue()));
579 }
580
581 propertyData = bof.createPropertyIntegerData(id, list);
582 } else {
583 throwWrongTypeError(firstValue, "integer", BigInteger.class, id);
584 }
585 } else if (definition instanceof PropertyBooleanDefinition) {
586 if (firstValue == null) {
587 propertyData = bof.createPropertyBooleanData(id, (List<Boolean>) null);
588 } else if (firstValue instanceof Boolean) {
589 propertyData = bof.createPropertyBooleanData(id, (List<Boolean>) values);
590 } else {
591 throwWrongTypeError(firstValue, "boolean", Boolean.class, id);
592 }
593 } else if (definition instanceof PropertyDecimalDefinition) {
594 if (firstValue == null) {
595 propertyData = bof.createPropertyDecimalData(id, (List<BigDecimal>) null);
596 } else if (firstValue instanceof BigDecimal) {
597 propertyData = bof.createPropertyDecimalData(id, (List<BigDecimal>) values);
598 } else if ((firstValue instanceof Float) || (firstValue instanceof Double)
599 || (firstValue instanceof Byte) || (firstValue instanceof Short)
600 || (firstValue instanceof Integer) || (firstValue instanceof Long)) {
601
602
603 List<BigDecimal> list = new ArrayList<BigDecimal>(values.size());
604 for (Object v : values) {
605 list.add(new BigDecimal(v.toString()));
606 }
607
608 propertyData = bof.createPropertyDecimalData(id, list);
609 } else {
610 throwWrongTypeError(firstValue, "decimal", BigDecimal.class, id);
611 }
612 } else if (definition instanceof PropertyDateTimeDefinition) {
613 if (firstValue == null) {
614 propertyData = bof.createPropertyDateTimeData(id, (List<GregorianCalendar>) null);
615 } else if (firstValue instanceof GregorianCalendar) {
616 propertyData = bof.createPropertyDateTimeData(id, (List<GregorianCalendar>) values);
617 } else if (firstValue instanceof Date) {
618 List<GregorianCalendar> list = new ArrayList<GregorianCalendar>(values.size());
619 for (Object d : values) {
620 GregorianCalendar cal = new GregorianCalendar();
621 cal.setTimeZone(DateTimeHelper.GMT);
622 cal.setTime((Date) d);
623 list.add(cal);
624 }
625 propertyData = bof.createPropertyDateTimeData(id, list);
626 } else {
627 throwWrongTypeError(firstValue, "datetime", GregorianCalendar.class, id);
628 }
629 }
630
631
632 if (propertyData == null) {
633 throw new IllegalArgumentException("Property '" + id + "' doesn't match the property defintion!");
634 }
635
636 propertyList.add(propertyData);
637 }
638
639 return bof.createPropertiesData(propertyList);
640 }
641
642 @Override
643 public List<PropertyData<?>> convertQueryProperties(Properties properties) {
644
645 if ((properties == null) || (properties.getProperties() == null)) {
646 throw new IllegalArgumentException("Properties must be set!");
647 }
648 return new ArrayList<PropertyData<?>>(properties.getPropertyList());
649 }
650
651
652
653 @Override
654 public CmisObject convertObject(ObjectData objectData, OperationContext context) {
655 if (objectData == null) {
656 throw new IllegalArgumentException("Object data is null!");
657 }
658
659 if (objectData.getId() == null) {
660 throw new IllegalArgumentException("Object ID property not set!");
661 }
662
663 if (objectData.getBaseTypeId() == null) {
664 throw new IllegalArgumentException("Base type ID property not set!");
665 }
666
667 ObjectType type = getTypeFromObjectData(objectData);
668
669
670 switch (objectData.getBaseTypeId()) {
671 case CMIS_DOCUMENT:
672 return new DocumentImpl((SessionImpl) session, type, objectData, context);
673 case CMIS_FOLDER:
674 return new FolderImpl((SessionImpl) session, type, objectData, context);
675 case CMIS_POLICY:
676 return new PolicyImpl((SessionImpl) session, type, objectData, context);
677 case CMIS_RELATIONSHIP:
678 return new RelationshipImpl((SessionImpl) session, type, objectData, context);
679 case CMIS_ITEM:
680 return new ItemImpl((SessionImpl) session, type, objectData, context);
681 case CMIS_SECONDARY:
682 throw new CmisRuntimeException("Secondary type is used as object type: " + objectData.getBaseTypeId());
683 default:
684 throw new CmisRuntimeException("Unsupported base type: " + objectData.getBaseTypeId());
685 }
686 }
687
688 @Override
689 public QueryResult convertQueryResult(ObjectData objectData) {
690 if (objectData == null) {
691 throw new IllegalArgumentException("Object data is null!");
692 }
693
694 return new QueryResultImpl(session, objectData);
695 }
696
697 @Override
698 public ChangeEvent convertChangeEvent(ObjectData objectData) {
699 ChangeType changeType = null;
700 GregorianCalendar changeTime = null;
701 String objectId = null;
702 Map<String, List<?>> properties = null;
703 List<String> policyIds = null;
704 Acl acl = null;
705
706 if (objectData.getChangeEventInfo() != null) {
707 changeType = objectData.getChangeEventInfo().getChangeType();
708 changeTime = objectData.getChangeEventInfo().getChangeTime();
709 }
710
711 if ((objectData.getProperties() != null) && (objectData.getProperties().getPropertyList() != null)) {
712 properties = new HashMap<String, List<?>>(objectData.getProperties().getPropertyList().size());
713
714 for (PropertyData<?> property : objectData.getProperties().getPropertyList()) {
715 properties.put(property.getId(), property.getValues());
716 }
717
718 if (properties.containsKey(PropertyIds.OBJECT_ID)) {
719 List<?> objectIdList = properties.get(PropertyIds.OBJECT_ID);
720 if (isNotEmpty(objectIdList)) {
721 objectId = objectIdList.get(0).toString();
722 }
723 }
724
725 if ((objectData.getPolicyIds() != null) && (objectData.getPolicyIds().getPolicyIds() != null)) {
726 policyIds = objectData.getPolicyIds().getPolicyIds();
727 }
728
729 if (objectData.getAcl() != null) {
730 acl = objectData.getAcl();
731 }
732 }
733
734 return new ChangeEventImpl(changeType, changeTime, objectId, properties, policyIds, acl);
735 }
736
737 @Override
738 public ChangeEvents convertChangeEvents(String changeLogToken, ObjectList objectList) {
739 if (objectList == null) {
740 return null;
741 }
742
743 List<ChangeEvent> events = new ArrayList<ChangeEvent>();
744 if (objectList.getObjects() != null) {
745 for (ObjectData objectData : objectList.getObjects()) {
746 if (objectData == null) {
747 continue;
748 }
749
750 events.add(convertChangeEvent(objectData));
751 }
752 }
753
754 boolean hasMoreItems = objectList.hasMoreItems() == null ? false : objectList.hasMoreItems().booleanValue();
755 long totalNumItems = objectList.getNumItems() == null ? -1 : objectList.getNumItems().longValue();
756
757 return new ChangeEventsImpl(changeLogToken, events, hasMoreItems, totalNumItems);
758 }
759
760 private void throwWrongTypeError(Object obj, String type, Class<?> clazz, String id) {
761 String expectedTypes;
762 if (BigInteger.class.isAssignableFrom(clazz)) {
763 expectedTypes = "<BigInteger, Byte, Short, Integer, Long>";
764 } else if (BigDecimal.class.isAssignableFrom(clazz)) {
765 expectedTypes = "<BigDecimal, Double, Float, Byte, Short, Integer, Long>";
766 } else if (GregorianCalendar.class.isAssignableFrom(clazz)) {
767 expectedTypes = "<java.util.GregorianCalendar, java.util.Date>";
768 } else {
769 expectedTypes = clazz.getName();
770 }
771
772 String message = "Property '" + id + "' is a " + type + " property. Expected type '" + expectedTypes
773 + "' but received a '" + obj.getClass().getName() + "' property.";
774
775 throw new IllegalArgumentException(message);
776 }
777 }