View Javadoc

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.inmemory.server;
20  
21  import java.math.BigDecimal;
22  import java.math.BigInteger;
23  import java.util.Collection;
24  import java.util.List;
25  import java.util.ListIterator;
26  import java.util.Map;
27  import java.util.Set;
28  
29  import org.apache.chemistry.opencmis.commons.data.Acl;
30  import org.apache.chemistry.opencmis.commons.data.CreatablePropertyTypes;
31  import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
32  import org.apache.chemistry.opencmis.commons.data.NewTypeSettableAttributes;
33  import org.apache.chemistry.opencmis.commons.data.Properties;
34  import org.apache.chemistry.opencmis.commons.data.RepositoryCapabilities;
35  import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
36  import org.apache.chemistry.opencmis.commons.definitions.Choice;
37  import org.apache.chemistry.opencmis.commons.definitions.PropertyDecimalDefinition;
38  import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
39  import org.apache.chemistry.opencmis.commons.definitions.PropertyIntegerDefinition;
40  import org.apache.chemistry.opencmis.commons.definitions.PropertyStringDefinition;
41  import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
42  import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionContainer;
43  import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
44  import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
45  import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
46  import org.apache.chemistry.opencmis.commons.enums.PropertyType;
47  import org.apache.chemistry.opencmis.commons.enums.RelationshipDirection;
48  import org.apache.chemistry.opencmis.commons.enums.UnfileObject;
49  import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
50  import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
51  import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
52  import org.apache.chemistry.opencmis.commons.server.CallContext;
53  import org.apache.chemistry.opencmis.commons.spi.Holder;
54  import org.apache.chemistry.opencmis.inmemory.storedobj.api.CmisServiceValidator;
55  import org.apache.chemistry.opencmis.inmemory.storedobj.api.ObjectStore;
56  import org.apache.chemistry.opencmis.inmemory.storedobj.api.Policy;
57  import org.apache.chemistry.opencmis.inmemory.storedobj.api.StoreManager;
58  import org.apache.chemistry.opencmis.inmemory.storedobj.api.StoredObject;
59  
60  public class BaseServiceValidatorImpl implements CmisServiceValidator {
61  
62      protected static final String UNKNOWN_OBJECT_ID = "Unknown object id: ";
63      protected static final String UNKNOWN_REPOSITORY_ID = "Unknown repository id: ";
64      protected static final String OBJECT_ID_CANNOT_BE_NULL = "Object Id cannot be null.";
65      protected static final String REPOSITORY_ID_CANNOT_BE_NULL = "Repository Id cannot be null.";
66      protected static final String UNKNOWN_TYPE_ID = "Unknown type id: ";
67      protected static final String TYPE_ID_CANNOT_BE_NULL = "Type Id cannot be null.";
68      protected final StoreManager fStoreManager;
69  
70      public BaseServiceValidatorImpl(StoreManager sm) {
71          fStoreManager = sm;
72      }
73  
74      /**
75       * Check if repository is known and that object exists. To avoid later calls
76       * to again retrieve the object from the id return the retrieved object for
77       * later use.
78       * 
79       * @param repositoryId
80       *            repository id
81       * @param objectId
82       *            object id
83       * @return object for objectId
84       */
85      protected StoredObject checkStandardParameters(String repositoryId, String objectId) {
86          if (null == repositoryId) {
87              throw new CmisInvalidArgumentException(REPOSITORY_ID_CANNOT_BE_NULL);
88          }
89  
90          if (null == objectId) {
91              throw new CmisInvalidArgumentException(OBJECT_ID_CANNOT_BE_NULL);
92          }
93  
94          ObjectStore objStore = fStoreManager.getObjectStore(repositoryId);
95  
96          if (objStore == null) {
97              throw new CmisObjectNotFoundException(UNKNOWN_REPOSITORY_ID + repositoryId);
98          }
99  
100         StoredObject so = objStore.getObjectById(objectId);
101 
102         if (so == null) {
103             throw new CmisObjectNotFoundException(UNKNOWN_OBJECT_ID + objectId);
104         }
105 
106         return so;
107     }
108 
109     protected StoredObject checkStandardParametersByPath(String repositoryId, String path, String user) {
110         if (null == repositoryId) {
111             throw new CmisInvalidArgumentException(REPOSITORY_ID_CANNOT_BE_NULL);
112         }
113 
114         if (null == path) {
115             throw new CmisInvalidArgumentException("Path parameter cannot be null.");
116         }
117 
118         ObjectStore objStore = fStoreManager.getObjectStore(repositoryId);
119 
120         if (objStore == null) {
121             throw new CmisObjectNotFoundException(UNKNOWN_REPOSITORY_ID + repositoryId);
122         }
123 
124         StoredObject so = objStore.getObjectByPath(path, user);
125 
126         if (so == null) {
127             throw new CmisObjectNotFoundException("Unknown path: " + path);
128         }
129 
130         return so;
131     }
132 
133     protected StoredObject checkStandardParametersAllowNull(String repositoryId, String objectId) {
134 
135         StoredObject so = null;
136 
137         if (null == repositoryId) {
138             throw new CmisInvalidArgumentException(REPOSITORY_ID_CANNOT_BE_NULL);
139         }
140 
141         if (null != objectId) {
142 
143             ObjectStore objStore = fStoreManager.getObjectStore(repositoryId);
144 
145             if (objStore == null) {
146                 throw new CmisObjectNotFoundException(UNKNOWN_REPOSITORY_ID + repositoryId);
147             }
148 
149             so = objStore.getObjectById(objectId);
150 
151             if (so == null) {
152                 throw new CmisObjectNotFoundException(UNKNOWN_OBJECT_ID + objectId);
153             }
154         }
155 
156         return so;
157     }
158 
159     protected StoredObject checkExistingObjectId(ObjectStore objStore, String objectId) {
160 
161         if (null == objectId) {
162             throw new CmisInvalidArgumentException(OBJECT_ID_CANNOT_BE_NULL);
163         }
164 
165         StoredObject so = objStore.getObjectById(objectId);
166 
167         if (so == null) {
168             throw new CmisObjectNotFoundException(UNKNOWN_OBJECT_ID + objectId);
169         }
170 
171         return so;
172     }
173 
174     protected void checkRepositoryId(String repositoryId) {
175         if (null == repositoryId) {
176             throw new CmisInvalidArgumentException(REPOSITORY_ID_CANNOT_BE_NULL);
177         }
178 
179         ObjectStore objStore = fStoreManager.getObjectStore(repositoryId);
180 
181         if (objStore == null) {
182             throw new CmisInvalidArgumentException(UNKNOWN_REPOSITORY_ID + repositoryId);
183         }
184     }
185 
186     protected StoredObject[] checkParams(String repositoryId, String objectId1, String objectId2) {
187         StoredObject[] so = new StoredObject[2];
188         checkRepositoryId(repositoryId);
189         ObjectStore objectStore = fStoreManager.getObjectStore(repositoryId);
190         so[0] = checkExistingObjectId(objectStore, objectId1);
191         so[1] = checkExistingObjectId(objectStore, objectId2);
192         return so;
193     }
194 
195     protected void checkPolicies(CallContext context, String repositoryId, List<String> policyIds) {
196         if (policyIds != null && policyIds.size() > 0) {
197         	boolean cmis11 = context.getCmisVersion() != CmisVersion.CMIS_1_0;
198             for (String policyId : policyIds) {
199                 TypeDefinitionContainer tdc = fStoreManager.getTypeById(repositoryId, policyId, cmis11);
200                 if (tdc == null) {
201                     throw new CmisInvalidArgumentException("Unknown policy type: " + policyId);
202                 }
203                 if (tdc.getTypeDefinition().getBaseTypeId() != BaseTypeId.CMIS_POLICY) {
204                     throw new CmisInvalidArgumentException(policyId + " is not a policy type");
205                 }
206             }
207         }
208     }
209 
210     protected void checkCreatablePropertyTypes(CallContext context, String repositoryId,
211             Collection<PropertyDefinition<?>> propertyDefinitions) {
212         RepositoryInfo repositoryInfo = fStoreManager.getRepositoryInfo(context, repositoryId);
213         RepositoryCapabilities repositoryCapabilities = repositoryInfo.getCapabilities();
214         if (null == repositoryCapabilities) {
215         	return;
216         }
217         CreatablePropertyTypes creatablePropertyTypes = repositoryCapabilities.getCreatablePropertyTypes();
218         if (null == creatablePropertyTypes) {
219         	return;
220         }
221 
222         Set<PropertyType> creatablePropertyTypeSet = creatablePropertyTypes.canCreate();
223         if (null == creatablePropertyTypeSet) {
224         	return;
225         }
226 
227         for (PropertyDefinition<?> propertyDefinition : propertyDefinitions) {
228             if (!creatablePropertyTypeSet.contains(propertyDefinition.getPropertyType()))
229                 throw new CmisConstraintException("propertyDefinition " + propertyDefinition.getId()
230                         + "is of not creatable type " + propertyDefinition.getPropertyType());
231 
232             // mandatory properties must have a default value
233             if (Boolean.TRUE.equals(propertyDefinition.isRequired()) && (propertyDefinition.getDefaultValue() == null)) {
234                 throw new CmisConstraintException("property: " + propertyDefinition.getId()
235                         + "required properties must have a default value");
236             }
237         }
238     }
239 
240     protected void checkSettableAttributes(CallContext context, String repositoryId, TypeDefinition oldTypeDefinition,
241             TypeDefinition newTypeDefinition) {
242         RepositoryInfo repositoryInfo = fStoreManager.getRepositoryInfo(context, repositoryId);
243         RepositoryCapabilities repositoryCapabilities = repositoryInfo.getCapabilities();
244         NewTypeSettableAttributes newTypeSettableAttributes = repositoryCapabilities.getNewTypeSettableAttributes();
245 
246         if (null == newTypeSettableAttributes)
247             return; // no restrictions defined
248         if (Boolean.TRUE.equals( newTypeSettableAttributes.canSetControllableAcl())
249         		&& Boolean.TRUE.equals( newTypeSettableAttributes.canSetControllablePolicy())
250         		&& Boolean.TRUE.equals(newTypeSettableAttributes.canSetCreatable()) 
251         		&& Boolean.TRUE.equals(newTypeSettableAttributes.canSetDescription())
252         		&& Boolean.TRUE.equals(newTypeSettableAttributes.canSetDisplayName()) 
253         		&& Boolean.TRUE.equals(newTypeSettableAttributes.canSetFileable())
254         		&& Boolean.TRUE.equals(newTypeSettableAttributes.canSetFulltextIndexed()) 
255         		&& Boolean.TRUE.equals(newTypeSettableAttributes.canSetId())
256         		&& Boolean.TRUE.equals(newTypeSettableAttributes.canSetIncludedInSupertypeQuery())
257         		&& Boolean.TRUE.equals(newTypeSettableAttributes.canSetLocalName()) 
258         		&& Boolean.TRUE.equals(newTypeSettableAttributes.canSetLocalNamespace())
259         		&& Boolean.TRUE.equals(newTypeSettableAttributes.canSetQueryable()) 
260         		&& Boolean.TRUE.equals(newTypeSettableAttributes.canSetQueryName()))
261             return; // all is allowed
262         if (Boolean.FALSE.equals(newTypeSettableAttributes.canSetControllableAcl())
263                 && !isSameAs(oldTypeDefinition.isControllableAcl(), newTypeDefinition.isControllableAcl()))
264             throw new CmisConstraintException("controllableAcl is not settable in repository " + repositoryId
265                     + ", but " + oldTypeDefinition.getId() + " and " + newTypeDefinition.getId()
266                     + " differ in controllableAcl");
267         if (Boolean.FALSE.equals(newTypeSettableAttributes.canSetControllablePolicy())
268                 && !isSameAs(oldTypeDefinition.isControllablePolicy(), newTypeDefinition.isControllablePolicy()))
269             throw new CmisConstraintException("controllablePolicy is not settable in repository " + repositoryId
270                     + ", but " + oldTypeDefinition.getId() + " and " + newTypeDefinition.getId()
271                     + " differ in controllablePolicy");
272         if (Boolean.FALSE.equals(newTypeSettableAttributes.canSetCreatable())
273                 && !isSameAs(oldTypeDefinition.isCreatable(), newTypeDefinition.isCreatable()))
274             throw new CmisConstraintException("isCreatable is not settable in repository " + repositoryId + ", but "
275                     + oldTypeDefinition.getId() + " and " + newTypeDefinition.getId() + " differ in isCreatable");
276         if (Boolean.FALSE.equals(newTypeSettableAttributes.canSetDescription())
277                 && !isSameAs(oldTypeDefinition.getDescription(), newTypeDefinition.getDescription()))
278             throw new CmisConstraintException("description is not settable in repository " + repositoryId + ", but "
279                     + oldTypeDefinition.getId() + " and " + newTypeDefinition.getId() + " differ in their description");
280         if (Boolean.FALSE.equals(newTypeSettableAttributes.canSetDisplayName())
281                 && !isSameAs(oldTypeDefinition.getDisplayName(), newTypeDefinition.getDisplayName()))
282             throw new CmisConstraintException("displayName is not settable in repository " + repositoryId + ", but "
283                     + oldTypeDefinition.getId() + " and " + newTypeDefinition.getId() + " differ in their displayName");
284         if (Boolean.FALSE.equals(newTypeSettableAttributes.canSetFileable())
285                 && !isSameAs(oldTypeDefinition.isFileable(), newTypeDefinition.isFileable()))
286             throw new CmisConstraintException("fileable is not settable in repository " + repositoryId + ", but "
287                     + oldTypeDefinition.getId() + " and " + newTypeDefinition.getId() + " differ in isFileable");
288         if (Boolean.FALSE.equals(newTypeSettableAttributes.canSetFulltextIndexed())
289                 && !isSameAs(oldTypeDefinition.isFulltextIndexed(), newTypeDefinition.isFulltextIndexed()))
290             throw new CmisConstraintException("fulltextIndexed is not settable in repository " + repositoryId
291                     + ", but " + oldTypeDefinition.getId() + " and " + newTypeDefinition.getId()
292                     + " differ in isFulltextIndexed");
293         if (Boolean.FALSE.equals(newTypeSettableAttributes.canSetId()) && !isSameAs(oldTypeDefinition.getId(), newTypeDefinition.getId()))
294             throw new CmisConstraintException("id is not settable in repository " + repositoryId + ", but "
295                     + oldTypeDefinition.getId() + " and " + newTypeDefinition.getId() + " differ in their id");
296         if (Boolean.FALSE.equals(newTypeSettableAttributes.canSetIncludedInSupertypeQuery())
297                 && !isSameAs(oldTypeDefinition.isIncludedInSupertypeQuery(), newTypeDefinition.isIncludedInSupertypeQuery()))
298             throw new CmisConstraintException("includedInSupertypeQuery is not settable in repository " + repositoryId
299                     + ", but " + oldTypeDefinition.getId() + " and " + newTypeDefinition.getId()
300                     + " differ in their isIncludedInSupertypeQuery");
301         if (Boolean.FALSE.equals(newTypeSettableAttributes.canSetLocalName())
302                 && !isSameAs(oldTypeDefinition.getLocalName(), newTypeDefinition.getLocalName()))
303             throw new CmisConstraintException("localName is not settable in repository " + repositoryId + ", but "
304                     + oldTypeDefinition.getId() + " and " + newTypeDefinition.getId() + " differ in their localName");
305         if (Boolean.FALSE.equals(newTypeSettableAttributes.canSetLocalNamespace())
306                 && !isSameAs(oldTypeDefinition.getLocalNamespace(), newTypeDefinition.getLocalNamespace()))
307             throw new CmisConstraintException("localNamespace is not settable in repository " + repositoryId + ", but "
308                     + oldTypeDefinition.getId() + " and " + newTypeDefinition.getId()
309                     + " differ in their localNamespace");
310         if (Boolean.FALSE.equals(newTypeSettableAttributes.canSetQueryable())
311                 && !isSameAs(oldTypeDefinition.isQueryable(), newTypeDefinition.isQueryable()))
312             throw new CmisConstraintException("queryable is not settable in repository " + repositoryId + ", but "
313                     + oldTypeDefinition.getId() + " and " + newTypeDefinition.getId() + " differ in their isQueryable");
314         if (Boolean.FALSE.equals(newTypeSettableAttributes.canSetQueryName())
315                 && !isSameAs(oldTypeDefinition.getQueryName(), newTypeDefinition.getQueryName()))
316             throw new CmisConstraintException("queryName is not settable in repository " + repositoryId + ", but "
317                     + oldTypeDefinition.getId() + " and " + newTypeDefinition.getId() + " differ in their queryName");
318     }
319 
320     // returns true if both are null or equal, avoid NPE
321     public static boolean isSameAs(Object object1, Object object2) {
322         if (object1 == object2) {
323             return true;
324         }
325         if ((object1 == null) || (object2 == null)) {
326             return false;
327         }
328         return object1.equals(object2);
329     }
330   
331     protected void checkUpdatePropertyDefinitions(Map<String, PropertyDefinition<?>> oldPropertyDefinitions,
332             Map<String, PropertyDefinition<?>> newPropertyDefinitions) {
333         for (PropertyDefinition<?> newPropertyDefinition : newPropertyDefinitions.values()) {
334             PropertyDefinition<?> oldPropertyDefinition = oldPropertyDefinitions.get(newPropertyDefinition.getId());
335 
336             if (Boolean.TRUE.equals(oldPropertyDefinition.isInherited()))
337                 throw new CmisConstraintException("property: " + oldPropertyDefinition.getId()
338                         + " update of inherited properties is not allowed");
339             if (!(Boolean.TRUE.equals(oldPropertyDefinition.isRequired())) && Boolean.TRUE.equals(newPropertyDefinition.isRequired()))
340                 throw new CmisConstraintException("property: " + oldPropertyDefinition.getId()
341                         + " optional properties must not be changed to required");
342             if (!isSameAs(oldPropertyDefinition.getPropertyType(), newPropertyDefinition.getPropertyType()))
343                 throw new CmisConstraintException("property: " + oldPropertyDefinition.getId()
344                         + " cannot update the propertyType (" + oldPropertyDefinition.getPropertyType() + ")");
345             if (!isSameAs(oldPropertyDefinition.getCardinality(), newPropertyDefinition.getCardinality()))
346                 throw new CmisConstraintException("property: " + oldPropertyDefinition.getId()
347                         + " cannot update the cardinality (" + oldPropertyDefinition.getCardinality() + ")");
348 
349             if (!isSameAs(oldPropertyDefinition.isOpenChoice(), newPropertyDefinition.isOpenChoice()))
350                 throw new CmisConstraintException("property: " + oldPropertyDefinition.getId()
351                         + " open choice cannot change from true to false");
352 
353             // check choices
354             if (Boolean.FALSE.equals(oldPropertyDefinition.isOpenChoice())) {
355                 List<?> oldChoices = oldPropertyDefinition.getChoices();
356                 if (null == oldChoices)
357                     throw new CmisConstraintException("property: " + oldPropertyDefinition.getId()
358                             + " there should be any choices when it's no open choice");
359                 List<?> newChoices = newPropertyDefinition.getChoices();
360                 if (null == newChoices)
361                     throw new CmisConstraintException("property: " + newPropertyDefinition.getId()
362                             + " there should be any choices when it's no open choice");
363                 ListIterator<?> newChoicesIterator = newChoices.listIterator();
364                 for (Object oldChoiceObject : oldChoices) {
365                     Object newChoiceObject = newChoicesIterator.next();
366                     if (!(oldChoiceObject instanceof Choice))
367                         throw new CmisConstraintException("property: " + newPropertyDefinition.getId()
368                                 + " old choice object is not of class Choice: " + oldChoiceObject.toString());
369                     if (!(newChoiceObject instanceof Choice))
370                         throw new CmisConstraintException("property: " + newPropertyDefinition.getId()
371                                 + " new choice object is not of class Choice: " + newChoiceObject.toString());
372                     Choice<?> oldChoice = (Choice<?>) oldChoiceObject;
373                     Choice<?> newChoice = (Choice<?>) newChoiceObject;
374                     List<?> oldValues = oldChoice.getValue();
375                     List<?> newValues = newChoice.getValue();
376                     for (Object oldValue : oldValues) {
377                         if (!newValues.contains(oldValue))
378                             throw new CmisConstraintException("property: " + newPropertyDefinition.getId() + " value: "
379                                     + oldValue.toString() + " is not in new values of the new choice");
380                     }
381                 }
382             }
383 
384             // check restrictions
385             if (oldPropertyDefinition instanceof PropertyDecimalDefinition) {
386                 PropertyDecimalDefinition oldPropertyDecimalDefinition = (PropertyDecimalDefinition) oldPropertyDefinition;
387                 PropertyDecimalDefinition newPropertyDecimalDefinition = (PropertyDecimalDefinition) newPropertyDefinition;
388 
389                 BigDecimal oldMinValue = oldPropertyDecimalDefinition.getMinValue();
390                 BigDecimal newMinValue = newPropertyDecimalDefinition.getMinValue();
391                 if (null != newMinValue && (oldMinValue == null || (newMinValue.compareTo(oldMinValue) > 0)))
392                     throw new CmisConstraintException("property: " + oldPropertyDefinition.getId() + " minValue "
393                             + oldMinValue + " cannot be further restricted to " + newMinValue);
394 
395                 BigDecimal oldMaxValue = oldPropertyDecimalDefinition.getMaxValue();
396                 BigDecimal newMaxValue = newPropertyDecimalDefinition.getMaxValue();
397                 if (null != newMaxValue && (oldMaxValue == null || (newMaxValue.compareTo(oldMaxValue) < 0)))
398                     throw new CmisConstraintException("property: " + oldPropertyDefinition.getId() + " maxValue "
399                             + oldMaxValue + " cannot be further restricted to " + newMaxValue);
400             }
401             if (oldPropertyDefinition instanceof PropertyIntegerDefinition) {
402                 PropertyIntegerDefinition oldPropertyIntegerDefinition = (PropertyIntegerDefinition) oldPropertyDefinition;
403                 PropertyIntegerDefinition newPropertyIntegerDefinition = (PropertyIntegerDefinition) newPropertyDefinition;
404 
405                 BigInteger oldMinValue = oldPropertyIntegerDefinition.getMinValue();
406                 BigInteger newMinValue = newPropertyIntegerDefinition.getMinValue();
407                 if (null != newMinValue && (oldMinValue == null || (newMinValue.compareTo(oldMinValue) > 0)))
408                     throw new CmisConstraintException("property: " + oldPropertyDefinition.getId() + " minValue "
409                             + oldMinValue + " cannot be further restricted to " + newMinValue);
410 
411                 BigInteger oldMaxValue = oldPropertyIntegerDefinition.getMaxValue();
412                 BigInteger newMaxValue = newPropertyIntegerDefinition.getMaxValue();
413                 if (null != newMaxValue && (oldMaxValue == null || (newMaxValue.compareTo(oldMaxValue) < 0)))
414                     throw new CmisConstraintException("property: " + oldPropertyDefinition.getId() + " maxValue "
415                             + oldMaxValue + " cannot be further restricted to " + newMaxValue);
416             }
417             if (oldPropertyDefinition instanceof PropertyStringDefinition) {
418                 PropertyStringDefinition oldPropertyStringDefinition = (PropertyStringDefinition) oldPropertyDefinition;
419                 PropertyStringDefinition newPropertyStringDefinition = (PropertyStringDefinition) newPropertyDefinition;
420 
421                 BigInteger oldMaxValue = oldPropertyStringDefinition.getMaxLength();
422                 BigInteger newMaxValue = newPropertyStringDefinition.getMaxLength();
423                 if (null != newMaxValue && (oldMaxValue == null || (newMaxValue.compareTo(oldMaxValue) < 0)))
424                     throw new CmisConstraintException("property: " + oldPropertyDefinition.getId() + " maxValue "
425                             + oldMaxValue + " cannot be further restricted to " + newMaxValue);
426             }
427         }
428 
429         // check for removed properties
430         for (PropertyDefinition<?> oldPropertyDefinition : oldPropertyDefinitions.values()) {
431             PropertyDefinition<?> newPropertyDefinition = newPropertyDefinitions.get(oldPropertyDefinition.getId());
432             if (null == newPropertyDefinition) {
433                 throw new CmisConstraintException("property: " + oldPropertyDefinition.getId()
434                         + " cannot remove that property");
435             }
436         }
437     }
438 
439     protected void checkUpdateType(TypeDefinition updateType, TypeDefinition type) {
440     	if (updateType.getId() == null) {
441             throw new CmisConstraintException("type id cannot be null: " + updateType.getDisplayName() + ", "
442                     + type.getId());
443     	}
444     	if (updateType.getBaseTypeId() == null) {
445             throw new CmisConstraintException("type base id cannot be null: " + updateType.getDisplayName() + ", "
446                     + type.getId());
447     	}
448         if (!updateType.getId().equals(type.getId()))
449             throw new CmisConstraintException("type to update must be of the same id: " + updateType.getId() + ", "
450                     + type.getId());
451         if (updateType.getBaseTypeId() != type.getBaseTypeId())
452             throw new CmisConstraintException("base type to update must be the same: " + updateType.getBaseTypeId()
453                     + ", " + type.getBaseTypeId());
454         // anything else should be ignored
455     }
456 
457     protected TypeDefinition checkExistingTypeId(String repositoryId, String typeId, boolean cmis11) {
458 
459         if (null == typeId) {
460             throw new CmisInvalidArgumentException(TYPE_ID_CANNOT_BE_NULL);
461         }
462 
463         TypeDefinitionContainer tdc = fStoreManager.getTypeById(repositoryId, typeId, cmis11);
464         if (tdc == null) {
465             throw new CmisObjectNotFoundException(UNKNOWN_TYPE_ID + typeId);
466         }
467 
468         return tdc.getTypeDefinition();
469     }
470 
471     protected void checkBasicType(TypeDefinition type) {
472     	if (type.getId() == null) {
473             throw new CmisConstraintException("type id cannot be null: " + type.getDisplayName() + ", "
474                     + type.getId());
475     	}
476         if (type.getId().equals(type.getBaseTypeId().value()))
477             throw new CmisInvalidArgumentException("type " + type.getId()
478                     + " is a basic type, basic types are read-only");
479     }
480 
481     @Override
482     public void getRepositoryInfos(CallContext context, ExtensionsData extension) {
483     }
484 
485     @Override
486     public void getRepositoryInfo(CallContext context, String repositoryId, ExtensionsData extension) {
487 
488         checkRepositoryId(repositoryId);
489     }
490 
491     @Override
492     public void getTypeChildren(CallContext context, String repositoryId, String typeId, ExtensionsData extension) {
493 
494         checkRepositoryId(repositoryId);
495     }
496 
497     @Override
498     public void getTypeDescendants(CallContext context, String repositoryId, String typeId, ExtensionsData extension) {
499 
500         checkRepositoryId(repositoryId);
501     }
502 
503     @Override
504     public void getTypeDefinition(CallContext context, String repositoryId, String typeId, ExtensionsData extension) {
505 
506         checkRepositoryId(repositoryId);
507     }
508 
509     @Override
510     public StoredObject getChildren(CallContext context, String repositoryId, String folderId, ExtensionsData extension) {
511 
512         return checkStandardParameters(repositoryId, folderId);
513     }
514 
515     @Override
516     public StoredObject getDescendants(CallContext context, String repositoryId, String folderId,
517             ExtensionsData extension) {
518 
519         return checkStandardParameters(repositoryId, folderId);
520     }
521 
522     @Override
523     public StoredObject getFolderTree(CallContext context, String repositoryId, String folderId,
524             ExtensionsData extension) {
525 
526         return checkStandardParameters(repositoryId, folderId);
527     }
528 
529     @Override
530     public StoredObject getObjectParents(CallContext context, String repositoryId, String objectId,
531             ExtensionsData extension) {
532 
533         return checkStandardParameters(repositoryId, objectId);
534     }
535 
536     @Override
537     public StoredObject getFolderParent(CallContext context, String repositoryId, String folderId,
538             ExtensionsData extension) {
539 
540         return checkStandardParameters(repositoryId, folderId);
541     }
542 
543     @Override
544     public StoredObject getCheckedOutDocs(CallContext context, String repositoryId, String folderId,
545             ExtensionsData extension) {
546 
547         if (null != folderId) {
548             return checkStandardParameters(repositoryId, folderId);
549         } else {
550             checkRepositoryId(repositoryId);
551             return null;
552         }
553 
554     }
555 
556     @Override
557     public StoredObject createDocument(CallContext context, String repositoryId, String folderId,
558             List<String> policyIds, ExtensionsData extension) {
559         return checkStandardParametersAllowNull(repositoryId, folderId);
560     }
561 
562     @Override
563     public StoredObject createDocumentFromSource(CallContext context, String repositoryId, String sourceId,
564             String folderId, List<String> policyIds, ExtensionsData extension) {
565 
566         return checkStandardParametersAllowNull(repositoryId, sourceId);
567     }
568 
569     @Override
570     public StoredObject createFolder(CallContext context, String repositoryId, String folderId, List<String> policyIds,
571             ExtensionsData extension) {
572         return checkStandardParameters(repositoryId, folderId);
573     }
574 
575     @Override
576     public StoredObject[] createRelationship(CallContext context, String repositoryId, String sourceId,
577             String targetId, List<String> policyIds, ExtensionsData extension) {
578         checkRepositoryId(repositoryId);
579         checkStandardParametersAllowNull(repositoryId, null);
580         return checkParams(repositoryId, sourceId, targetId);
581     }
582 
583     @Override
584     public StoredObject createPolicy(CallContext context, String repositoryId, String folderId, Acl addAces,
585             Acl removeAces, List<String> policyIds, ExtensionsData extension) {
586 
587         return checkStandardParametersAllowNull(repositoryId, folderId);
588     }
589 
590     // CMIS 1.1
591     @Override
592     public StoredObject createItem(CallContext context, String repositoryId, Properties properties, String folderId,
593             List<String> policies, Acl addAces, Acl removeAces, ExtensionsData extension) {
594         return checkStandardParametersAllowNull(repositoryId, folderId);
595     }
596 
597     @Override
598     public StoredObject getAllowableActions(CallContext context, String repositoryId, String objectId,
599             ExtensionsData extension) {
600         //
601         return checkStandardParameters(repositoryId, objectId);
602     }
603 
604     @Override
605     public StoredObject getObject(CallContext context, String repositoryId, String objectId, ExtensionsData extension) {
606 
607         StoredObject so = checkStandardParameters(repositoryId, objectId);
608         return so;
609     }
610 
611     @Override
612     public StoredObject getProperties(CallContext context, String repositoryId, String objectId,
613             ExtensionsData extension) {
614 
615         return checkStandardParameters(repositoryId, objectId);
616     }
617 
618     @Override
619     public StoredObject getRenditions(CallContext context, String repositoryId, String objectId,
620             ExtensionsData extension) {
621 
622         return checkStandardParameters(repositoryId, objectId);
623     }
624 
625     @Override
626     public StoredObject getObjectByPath(CallContext context, String repositoryId, String path, ExtensionsData extension) {
627 
628         return checkStandardParametersByPath(repositoryId, path, context.getUsername());
629     }
630 
631     @Override
632     public StoredObject getContentStream(CallContext context, String repositoryId, String objectId, String streamId,
633             ExtensionsData extension) {
634 
635         return checkStandardParameters(repositoryId, objectId);
636     }
637 
638     @Override
639     public StoredObject updateProperties(CallContext context, String repositoryId, Holder<String> objectId,
640             ExtensionsData extension) {
641 
642         return checkStandardParameters(repositoryId, objectId.getValue());
643     }
644 
645     @Override
646     public StoredObject[] moveObject(CallContext context, String repositoryId, Holder<String> objectId,
647             String targetFolderId, String sourceFolderId, ExtensionsData extension) {
648 
649         StoredObject[] res = new StoredObject[3];
650         res[0] = checkStandardParameters(repositoryId, objectId.getValue());
651         res[1] = checkExistingObjectId(fStoreManager.getObjectStore(repositoryId), sourceFolderId);
652         res[2] = checkExistingObjectId(fStoreManager.getObjectStore(repositoryId), targetFolderId);
653         return res;
654     }
655 
656     @Override
657     public StoredObject deleteObject(CallContext context, String repositoryId, String objectId, Boolean allVersions,
658             ExtensionsData extension) {
659 
660         return checkStandardParameters(repositoryId, objectId);
661     }
662 
663     @Override
664     public StoredObject deleteTree(CallContext context, String repositoryId, String folderId, Boolean allVersions,
665             UnfileObject unfileObjects, ExtensionsData extension) {
666         return checkStandardParameters(repositoryId, folderId);
667     }
668 
669     @Override
670     public StoredObject setContentStream(CallContext context, String repositoryId, Holder<String> objectId,
671             Boolean overwriteFlag, ExtensionsData extension) {
672 
673         return checkStandardParameters(repositoryId, objectId.getValue());
674     }
675 
676     @Override
677     public StoredObject appendContentStream(CallContext context, String repositoryId, Holder<String> objectId,
678             ExtensionsData extension) {
679         return checkStandardParameters(repositoryId, objectId.getValue());
680     }
681 
682     @Override
683     public StoredObject deleteContentStream(CallContext context, String repositoryId, Holder<String> objectId,
684             ExtensionsData extension) {
685         return checkStandardParameters(repositoryId, objectId.getValue());
686     }
687 
688     @Override
689     public StoredObject checkOut(CallContext context, String repositoryId, Holder<String> objectId,
690             ExtensionsData extension, Holder<Boolean> contentCopied) {
691 
692         return checkStandardParameters(repositoryId, objectId.getValue());
693     }
694 
695     @Override
696     public StoredObject cancelCheckOut(CallContext context, String repositoryId, String objectId,
697             ExtensionsData extension) {
698 
699         return checkStandardParameters(repositoryId, objectId);
700     }
701 
702     @Override
703     public StoredObject checkIn(CallContext context, String repositoryId, Holder<String> objectId, Acl addAces,
704             Acl removeAces, List<String> policyIds, ExtensionsData extension) {
705         return checkStandardParameters(repositoryId, objectId.getValue());
706     }
707 
708     @Override
709     public StoredObject getObjectOfLatestVersion(CallContext context, String repositoryId, String objectId,
710             String versionSeriesId, ExtensionsData extension) {
711 
712         return checkStandardParameters(repositoryId, versionSeriesId == null ? objectId : versionSeriesId);
713     }
714 
715     @Override
716     public StoredObject getPropertiesOfLatestVersion(CallContext context, String repositoryId, String objectId,
717             String versionSeriesId, ExtensionsData extension) {
718 
719         return checkStandardParameters(repositoryId, versionSeriesId == null ? objectId : versionSeriesId);
720     }
721 
722     @Override
723     public StoredObject getAllVersions(CallContext context, String repositoryId, String objectId,
724             String versionSeriesId, ExtensionsData extension) {
725 
726         return checkStandardParameters(repositoryId, versionSeriesId == null ? objectId : versionSeriesId);
727     }
728 
729     @Override
730     public void query(CallContext context, String repositoryId, ExtensionsData extension) {
731 
732         checkRepositoryId(repositoryId);
733     }
734 
735     @Override
736     public void getContentChanges(CallContext context, String repositoryId, ExtensionsData extension) {
737 
738         checkRepositoryId(repositoryId);
739     }
740 
741     @Override
742     public StoredObject[] addObjectToFolder(CallContext context, String repositoryId, String objectId, String folderId,
743             Boolean allVersions, ExtensionsData extension) {
744 
745         return checkParams(repositoryId, objectId, folderId);
746     }
747 
748     @Override
749     public StoredObject[] removeObjectFromFolder(CallContext context, String repositoryId, String objectId,
750             String folderId, ExtensionsData extension) {
751 
752         if (folderId != null) {
753             return checkParams(repositoryId, objectId, folderId);
754         } else {
755             StoredObject[] so = new StoredObject[1];
756             checkRepositoryId(repositoryId);
757             ObjectStore objectStore = fStoreManager.getObjectStore(repositoryId);
758             so[0] = checkExistingObjectId(objectStore, objectId);
759             return so;
760         }
761     }
762 
763     @Override
764     public StoredObject getObjectRelationships(CallContext context, String repositoryId, String objectId,
765             RelationshipDirection relationshipDirection, String typeId, ExtensionsData extension) {
766 
767         StoredObject so = checkStandardParameters(repositoryId, objectId);
768 
769         if (relationshipDirection == null) {
770             throw new CmisInvalidArgumentException("Relationship direction cannot be null.");
771         }
772 
773         if (typeId != null) {
774         	boolean cmis11 = context.getCmisVersion() != CmisVersion.CMIS_1_0;
775             TypeDefinition typeDef = fStoreManager.getTypeById(repositoryId, typeId, cmis11).getTypeDefinition();
776             if (typeDef == null) {
777                 throw new CmisInvalidArgumentException("Type Id " + typeId + " is not known in repository "
778                         + repositoryId);
779             }
780 
781             if (!typeDef.getBaseTypeId().equals(BaseTypeId.CMIS_RELATIONSHIP)) {
782                 throw new CmisInvalidArgumentException("Type Id " + typeId + " is not a relationship type.");
783             }
784         }
785         return so;
786     }
787 
788     @Override
789     public StoredObject getAcl(CallContext context, String repositoryId, String objectId, ExtensionsData extension) {
790 
791         return checkStandardParameters(repositoryId, objectId);
792     }
793 
794     @Override
795     public StoredObject applyAcl(CallContext context, String repositoryId, String objectId,
796             AclPropagation aclPropagation, ExtensionsData extension) {
797 
798         return checkStandardParameters(repositoryId, objectId);
799     }
800 
801     @Override
802     public StoredObject[] applyPolicy(CallContext context, String repositoryId, String policyId, String objectId,
803             ExtensionsData extension) {
804 
805         return checkParams(repositoryId, policyId, objectId);
806     }
807 
808     @Override
809     public StoredObject[] removePolicy(CallContext context, String repositoryId, String policyId, String objectId,
810             ExtensionsData extension) {
811 
812         StoredObject[] sos = checkParams(repositoryId, policyId, objectId);
813         StoredObject pol = sos[0];
814         if (!(pol instanceof Policy)) {
815             throw new CmisInvalidArgumentException("Id " + policyId + " is not a policy object.");
816         }
817         return sos;
818     }
819 
820     @Override
821     public StoredObject getAppliedPolicies(CallContext context, String repositoryId, String objectId,
822             ExtensionsData extension) {
823 
824         return checkStandardParameters(repositoryId, objectId);
825     }
826 
827     @Override
828     public StoredObject create(CallContext context, String repositoryId, String folderId, ExtensionsData extension) {
829 
830         return checkStandardParameters(repositoryId, folderId);
831     }
832 
833     public StoredObject deleteObjectOrCancelCheckOut(CallContext context, String repositoryId, String objectId,
834             ExtensionsData extension) {
835 
836         return checkStandardParameters(repositoryId, objectId);
837     }
838 
839     @Override
840     public StoredObject applyAcl(CallContext context, String repositoryId, String objectId) {
841 
842         return checkStandardParameters(repositoryId, objectId);
843     }
844 
845     @Override
846     public void createType(CallContext callContext, String repositoryId, TypeDefinition type, ExtensionsData extension) {
847         checkRepositoryId(repositoryId);
848 
849         if (null == type) {
850             throw new CmisInvalidArgumentException("Type cannot be null.");
851         }
852         String parentTypeId = type.getParentTypeId();
853         boolean cmis11 = callContext.getCmisVersion() != CmisVersion.CMIS_1_0;
854         TypeDefinitionContainer parentTypeContainer = fStoreManager.getTypeById(repositoryId, parentTypeId, cmis11);
855         if (null == parentTypeContainer) {
856             throw new CmisInvalidArgumentException(UNKNOWN_TYPE_ID + parentTypeId);
857         }
858         TypeDefinition parentType = parentTypeContainer.getTypeDefinition();
859         // check if type can be created
860         if (!(parentType.getTypeMutability().canCreate())) {
861             throw new CmisConstraintException("parent type: " + parentTypeId + " does not allow mutability create");
862         }
863         checkCreatablePropertyTypes(callContext, repositoryId, type.getPropertyDefinitions().values());
864     }
865 
866     @Override
867     public TypeDefinition updateType(CallContext callContext, String repositoryId, TypeDefinition type,
868             ExtensionsData extension) {
869         checkRepositoryId(repositoryId);
870 
871         boolean cmis11 = callContext.getCmisVersion() != CmisVersion.CMIS_1_0;
872         TypeDefinition updateType = checkExistingTypeId(repositoryId, type.getId(), cmis11);
873         checkUpdateType(updateType, type);
874         checkBasicType(type);
875         // check if type can be updated
876         if (!(updateType.getTypeMutability().canUpdate())) {
877             throw new CmisConstraintException("type: " + type.getId() + " does not allow mutability update");
878         }
879         checkCreatablePropertyTypes(callContext, repositoryId, type.getPropertyDefinitions().values());
880         checkSettableAttributes(callContext, repositoryId, updateType, type);
881         checkUpdatePropertyDefinitions(updateType.getPropertyDefinitions(), type.getPropertyDefinitions());
882         return updateType;
883     }
884 
885     @Override
886     public TypeDefinition deleteType(CallContext callContext, String repositoryId, String typeId,
887             ExtensionsData extension) {
888         checkRepositoryId(repositoryId);
889 
890         boolean cmis11 = callContext.getCmisVersion() != CmisVersion.CMIS_1_0;
891         TypeDefinition deleteType = checkExistingTypeId(repositoryId, typeId, cmis11);
892         checkBasicType(deleteType);
893         // check if type can be deleted
894         if (!(deleteType.getTypeMutability().canDelete())) {
895             throw new CmisConstraintException("type: " + typeId + " does not allow mutability delete");
896         }
897         return deleteType;
898     }
899 
900 }