This project has retired. For details please refer to its
Attic page.
TypeValidator 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.server.support;
20
21 import java.math.BigDecimal;
22 import java.math.BigInteger;
23 import java.util.ArrayList;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.apache.chemistry.opencmis.commons.PropertyIds;
29 import org.apache.chemistry.opencmis.commons.data.Acl;
30 import org.apache.chemistry.opencmis.commons.data.Properties;
31 import org.apache.chemistry.opencmis.commons.data.PropertyData;
32 import org.apache.chemistry.opencmis.commons.data.PropertyDecimal;
33 import org.apache.chemistry.opencmis.commons.data.PropertyInteger;
34 import org.apache.chemistry.opencmis.commons.definitions.Choice;
35 import org.apache.chemistry.opencmis.commons.definitions.DocumentTypeDefinition;
36 import org.apache.chemistry.opencmis.commons.definitions.PropertyDecimalDefinition;
37 import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
38 import org.apache.chemistry.opencmis.commons.definitions.PropertyIntegerDefinition;
39 import org.apache.chemistry.opencmis.commons.definitions.PropertyStringDefinition;
40 import org.apache.chemistry.opencmis.commons.definitions.RelationshipTypeDefinition;
41 import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
42 import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
43 import org.apache.chemistry.opencmis.commons.enums.Cardinality;
44 import org.apache.chemistry.opencmis.commons.enums.VersioningState;
45 import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
46 import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
47
48
49
50
51 public class TypeValidator {
52
53 public static void validateRequiredSystemProperties(Properties properties) {
54 if (properties == null || properties.getProperties() == null) {
55 throw new CmisInvalidArgumentException("Cannot create object, no properties are given");
56 }
57
58 if (!properties.getProperties().containsKey(PropertyIds.OBJECT_TYPE_ID)) {
59 throw new CmisInvalidArgumentException("Cannot create object, type id is missing");
60 }
61
62 }
63
64 private static boolean isMandatorySystemProperty(String propertyId) {
65
66 return propertyId.equals(PropertyIds.OBJECT_TYPE_ID);
67 }
68
69 @SuppressWarnings("unchecked")
70 static <T> PropertyValidator<T> createPropertyValidator(PropertyDefinition<?> propDef) {
71 PropertyValidator<T> result = null;
72 if (propDef instanceof PropertyIntegerDefinition) {
73 result = (PropertyValidator<T>) new PropertyValidatorInteger();
74 } else if (propDef instanceof PropertyDecimalDefinition) {
75 result = (PropertyValidator<T>) new PropertyValidatorDecimal();
76 } else if (propDef instanceof PropertyStringDefinition) {
77 result = (PropertyValidator<T>) new PropertyValidatorString();
78 } else {
79 result = new PropertyValidator<T>();
80 }
81 return result;
82 }
83
84
85
86
87
88
89
90 static class PropertyValidator<T> {
91
92 public void validate(PropertyDefinition<T> propDef, PropertyData<T> prop) {
93
94
95 if (propDef.getCardinality() == Cardinality.SINGLE && prop.getValues().size() > 1) {
96 throw new CmisConstraintException("The property with id " + propDef.getId()
97 + " is single valued, but multiple values are passed " + prop.getValues());
98 }
99
100 if (propDef.getChoices() != null && propDef.getChoices().size() > 0) {
101 validateChoices(propDef, prop);
102 }
103 }
104
105 private void validateChoices(PropertyDefinition<T> propDef, PropertyData<T> prop) {
106 boolean isAllowedValue = true;
107 boolean hasMultiValueChoiceLists = false;
108 for (Choice<?> allowedValue : propDef.getChoices()) {
109 if (allowedValue.getValue() != null && allowedValue.getValue().size() > 1) {
110 hasMultiValueChoiceLists = true;
111 }
112 }
113
114
115 if (hasMultiValueChoiceLists) {
116
117
118
119 isAllowedValue = false;
120 List<?> actualValues = prop.getValues();
121 for (Choice<?> allowedValue : propDef.getChoices()) {
122 if (allowedValue.getValue().size() == actualValues.size()) {
123 boolean listValuesAreEqual = true;
124 Iterator<?> it = allowedValue.getValue().iterator();
125 for (Object actualValue : actualValues) {
126 if (!actualValue.equals(it.next())) {
127 listValuesAreEqual = false;
128 break;
129 }
130 }
131 if (listValuesAreEqual) {
132 isAllowedValue = true;
133 }
134 }
135
136 if (isAllowedValue) {
137 break;
138 }
139 }
140
141 } else {
142 List<T> allowedValues = getAllowedValues(propDef.getChoices());
143
144
145 for (Object actualValue : prop.getValues()) {
146 if (!allowedValues.contains(actualValue)) {
147 isAllowedValue = false;
148 break;
149 }
150 }
151 }
152
153 if (!isAllowedValue) {
154 throw new CmisConstraintException("The property with id " + propDef.getId()
155 + " has a fixed set of values. Value(s) " + prop.getValues() + " are not listed.");
156 }
157 }
158
159
160
161
162
163
164
165
166
167 private List<T> getAllowedValues(List<Choice<T>> choices) {
168 List<T> allowedValues = new ArrayList<T>(choices.size());
169 for (Choice<T> choice : choices) {
170 if (choice.getValue() != null) {
171 allowedValues.add(choice.getValue().get(0));
172 }
173 if (choice.getChoice() != null) {
174 List<Choice<T>> x = choice.getChoice();
175 allowedValues.addAll(getAllowedValues(x));
176 }
177 }
178 return allowedValues;
179 }
180 }
181
182 static class PropertyValidatorInteger extends PropertyValidator<BigInteger> {
183
184 @Override
185 public void validate(PropertyDefinition<BigInteger> propDef, PropertyData<BigInteger> property) {
186
187 super.validate(propDef, property);
188
189 BigInteger propVal = property.getFirstValue();
190 BigInteger minVal = ((PropertyIntegerDefinition) propDef).getMinValue();
191 BigInteger maxVal = ((PropertyIntegerDefinition) propDef).getMaxValue();
192
193
194 if (minVal != null && propVal != null && propVal.compareTo(minVal) == -1) {
195 throw new CmisConstraintException("For property with id " + propDef.getId() + " the value " + propVal
196 + " is less than the minimum value " + minVal);
197 }
198 if (maxVal != null && propVal != null && propVal.compareTo(maxVal) == 1) {
199 throw new CmisConstraintException("For property with id " + propDef.getId() + " the value " + propVal
200 + " is bigger than the maximum value " + maxVal);
201 }
202 }
203 }
204
205 static class PropertyValidatorDecimal extends PropertyValidator<BigDecimal> {
206
207 @Override
208 public void validate(PropertyDefinition<BigDecimal> propDef, PropertyData<BigDecimal> property) {
209
210 super.validate(propDef, property);
211
212 BigDecimal propVal = property.getFirstValue();
213 BigDecimal minVal = ((PropertyDecimalDefinition) propDef).getMinValue();
214 BigDecimal maxVal = ((PropertyDecimalDefinition) propDef).getMaxValue();
215
216
217 if (minVal != null && propVal != null && propVal.compareTo(minVal) == -1) {
218 throw new CmisConstraintException("For property with id " + propDef.getId() + " the value " + propVal
219 + " is less than the minimum value " + minVal);
220 }
221 if (maxVal != null && propVal != null && propVal.compareTo(maxVal) == 1) {
222 throw new CmisConstraintException("For property with id " + propDef.getId() + " the value " + propVal
223 + " is bigger than the maximum value " + maxVal);
224 }
225 }
226 }
227
228 static class PropertyValidatorString extends PropertyValidator<String> {
229
230 @Override
231 public void validate(PropertyDefinition<String> propDef, PropertyData<String> property) {
232
233 super.validate(propDef, property);
234
235 long maxLen = ((PropertyStringDefinition) propDef).getMaxLength() == null ? -1
236 : ((PropertyStringDefinition) propDef).getMaxLength().longValue();
237 long len = property.getFirstValue() == null ? -1
238 : property.getFirstValue().length();
239
240
241 if (maxLen >= 0 && len >= 0 && maxLen < len) {
242 throw new CmisConstraintException("For property with id " + propDef.getId() + " the length of " + len
243 + "is bigger than the maximum allowed length " + maxLen);
244 }
245 }
246 }
247
248 @SuppressWarnings("unchecked")
249 public static <T> void validateProperties(TypeDefinition typeDef, Properties properties, boolean checkMandatory) {
250
251 List<String> propDefsRequired = getMandatoryPropDefs(typeDef.getPropertyDefinitions());
252
253 if(properties != null) {
254 for (PropertyData<?> prop : properties.getProperties().values()) {
255 String propertyId = prop.getId();
256 BaseTypeId baseTypeId = typeDef.getBaseTypeId();
257
258
259 if (checkMandatory && propDefsRequired.contains(propertyId)) {
260 propDefsRequired.remove(propertyId);
261 }
262
263 if (isSystemProperty(baseTypeId, propertyId)) {
264 continue;
265 }
266
267
268 if (!typeContainsProperty(typeDef, propertyId)) {
269 throw new CmisConstraintException("Unknown property "
270 + propertyId + " in type " + typeDef.getId());
271 }
272
273
274 PropertyDefinition<T> propDef = getPropertyDefinition(typeDef,
275 propertyId);
276 PropertyValidator<T> validator = createPropertyValidator(propDef);
277 validator.validate(propDef, (PropertyData<T>) prop);
278 }
279 }
280
281 if (checkMandatory && !propDefsRequired.isEmpty()) {
282 throw new CmisConstraintException("The following mandatory properties are missing: " + propDefsRequired);
283 }
284 }
285
286 public static void validateVersionStateForCreate(DocumentTypeDefinition typeDef, VersioningState verState) {
287 if (null == verState) {
288 return;
289 }
290 if (typeDef.isVersionable() && verState.equals(VersioningState.NONE) || !typeDef.isVersionable()
291 && !verState.equals(VersioningState.NONE)) {
292 throw new CmisConstraintException("The versioning state flag is imcompatible to the type definition.");
293 }
294
295 }
296
297 public static void validateAllowedChildObjectTypes(TypeDefinition childTypeDef, List<String> allowedChildTypes) {
298
299 validateAllowedTypes(childTypeDef, allowedChildTypes, "in this folder");
300 }
301
302 public static void validateAllowedRelationshipTypes (RelationshipTypeDefinition relationshipTypeDef, TypeDefinition sourceTypeDef,
303 TypeDefinition targetTypeDef)
304 {
305 List<String> allowedSourceTypes = relationshipTypeDef.getAllowedSourceTypeIds();
306 validateAllowedTypes(sourceTypeDef, allowedSourceTypes, " as source type in this relationship");
307 List<String> allowedTargetTypes = relationshipTypeDef.getAllowedTargetTypeIds();
308 validateAllowedTypes(targetTypeDef, allowedTargetTypes, " as target type in this relationship");
309 }
310
311 protected static void validateAllowedTypes(TypeDefinition typeDef, List<String> allowedTypes, String description)
312 {
313 if (null == allowedTypes || allowedTypes.size() == 0)
314 return;
315
316 for (String allowedType : allowedTypes) {
317 if (allowedType.equals(typeDef.getId()))
318 return;
319 }
320 throw new CmisConstraintException("The requested type " + typeDef.getId() + " is not allowed " + description);
321 }
322
323 public static void validateAcl(TypeDefinition typeDef, Acl addACEs, Acl removeACEs)
324 {
325 if (!typeDef.isControllableAcl() && (addACEs != null || removeACEs != null))
326 {
327 throw new CmisConstraintException("acl set for type: " + typeDef.getDisplayName() + " that is not controllableACL");
328 }
329 }
330
331 private static List<String> getMandatoryPropDefs(Map<String, PropertyDefinition<?>> propDefs) {
332 List<String> res = new ArrayList<String>();
333 if (null != propDefs) {
334 for (PropertyDefinition<?> propDef : propDefs.values()) {
335 if (propDef.isRequired() && !isMandatorySystemProperty(propDef.getId())) {
336 res.add(propDef.getId());
337 }
338 }
339 }
340 return res;
341 }
342
343 public static boolean typeContainsProperty(TypeDefinition typeDef, String propertyId) {
344
345 Map<String, PropertyDefinition<?>> propDefs = typeDef.getPropertyDefinitions();
346 if (null == propDefs) {
347 return false;
348 }
349
350 PropertyDefinition<?> propDef = propDefs.get(propertyId);
351
352 if (null == propDef) {
353 return false;
354 } else {
355 return true;
356 }
357 }
358
359 public static boolean typeContainsPropertyWithQueryName(TypeDefinition typeDef, String propertyQueryName) {
360
361 Map<String, PropertyDefinition<?>> propDefs = typeDef.getPropertyDefinitions();
362 if (null == propDefs) {
363 return false;
364 }
365
366 for (PropertyDefinition<?> propDef : propDefs.values()) {
367 if (propDef.getQueryName().toLowerCase().equals(propertyQueryName.toLowerCase())) {
368 return true;
369 }
370 }
371
372 return false;
373 }
374
375 @SuppressWarnings("unchecked")
376 private static <T> PropertyDefinition<T> getPropertyDefinition(TypeDefinition typeDef, String propertyId) {
377
378 Map<String, PropertyDefinition<?>> propDefs = typeDef.getPropertyDefinitions();
379 if (null == propDefs) {
380 return null;
381 }
382
383 PropertyDefinition<?> propDef = propDefs.get(propertyId);
384
385 if (null == propDef) {
386 return null;
387 } else {
388 return (PropertyDefinition<T>) propDef;
389 }
390 }
391
392 private static boolean isSystemProperty(BaseTypeId baseTypeId, String propertyId) {
393
394 if (propertyId.equals(PropertyIds.NAME)) {
395 return true;
396 } else if (propertyId.equals(PropertyIds.OBJECT_ID)) {
397 return true;
398 } else if (propertyId.equals(PropertyIds.OBJECT_TYPE_ID)) {
399 return true;
400 } else if (propertyId.equals(PropertyIds.BASE_TYPE_ID)) {
401 return true;
402 } else if (propertyId.equals(PropertyIds.CREATED_BY)) {
403 return true;
404 } else if (propertyId.equals(PropertyIds.CREATION_DATE)) {
405 return true;
406 } else if (propertyId.equals(PropertyIds.LAST_MODIFIED_BY)) {
407 return true;
408 } else if (propertyId.equals(PropertyIds.LAST_MODIFICATION_DATE)) {
409 return true;
410 } else if (propertyId.equals(PropertyIds.CHANGE_TOKEN)) {
411 return true;
412 }
413
414 if (baseTypeId.equals(BaseTypeId.CMIS_DOCUMENT)) {
415 if (propertyId.equals(PropertyIds.IS_IMMUTABLE)) {
416 return true;
417 } else if (propertyId.equals(PropertyIds.IS_LATEST_VERSION)) {
418 return true;
419 } else if (propertyId.equals(PropertyIds.IS_MAJOR_VERSION)) {
420 return true;
421 } else if (propertyId.equals(PropertyIds.VERSION_SERIES_ID)) {
422 return true;
423 } else if (propertyId.equals(PropertyIds.IS_LATEST_MAJOR_VERSION)) {
424 return true;
425 } else if (propertyId.equals(PropertyIds.VERSION_LABEL)) {
426 return true;
427 } else if (propertyId.equals(PropertyIds.VERSION_SERIES_ID)) {
428 return true;
429 } else if (propertyId.equals(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT)) {
430 return true;
431 } else if (propertyId.equals(PropertyIds.VERSION_SERIES_CHECKED_OUT_BY)) {
432 return true;
433 } else if (propertyId.equals(PropertyIds.VERSION_SERIES_CHECKED_OUT_ID)) {
434 return true;
435 } else if (propertyId.equals(PropertyIds.CHECKIN_COMMENT)) {
436 return true;
437 } else if (propertyId.equals(PropertyIds.CONTENT_STREAM_LENGTH)) {
438 return true;
439 } else if (propertyId.equals(PropertyIds.CONTENT_STREAM_MIME_TYPE)) {
440 return true;
441 } else if (propertyId.equals(PropertyIds.CONTENT_STREAM_FILE_NAME)) {
442 return true;
443 } else if (propertyId.equals(PropertyIds.CONTENT_STREAM_ID)) {
444 return true;
445 } else {
446 return false;
447 }
448 } else if (baseTypeId.equals(BaseTypeId.CMIS_FOLDER)) {
449 if (propertyId.equals(PropertyIds.PARENT_ID)) {
450 return true;
451 } else if (propertyId.equals(PropertyIds.ALLOWED_CHILD_OBJECT_TYPE_IDS)) {
452 return true;
453 } else if (propertyId.equals(PropertyIds.PATH)) {
454 return true;
455 } else {
456 return false;
457 }
458 } else if (baseTypeId.equals(BaseTypeId.CMIS_POLICY)) {
459 if (propertyId.equals(PropertyIds.SOURCE_ID)) {
460 return true;
461 } else if (propertyId.equals(PropertyIds.TARGET_ID)) {
462 return true;
463 } else {
464 return false;
465 }
466 } else {
467 if (propertyId.equals(PropertyIds.POLICY_TEXT)) {
468 return true;
469 } else {
470 return false;
471 }
472 }
473 }
474 }