This project has retired. For details please refer to its Attic page.
AbstractSessionTest xref
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.tck.impl;
20  
21  import static org.apache.chemistry.opencmis.commons.impl.CollectionsHelper.isNotEmpty;
22  import static org.apache.chemistry.opencmis.commons.impl.CollectionsHelper.isNullOrEmpty;
23  import static org.apache.chemistry.opencmis.tck.CmisTestResultStatus.FAILURE;
24  import static org.apache.chemistry.opencmis.tck.CmisTestResultStatus.INFO;
25  import static org.apache.chemistry.opencmis.tck.CmisTestResultStatus.OK;
26  import static org.apache.chemistry.opencmis.tck.CmisTestResultStatus.SKIPPED;
27  import static org.apache.chemistry.opencmis.tck.CmisTestResultStatus.UNEXPECTED_EXCEPTION;
28  import static org.apache.chemistry.opencmis.tck.CmisTestResultStatus.WARNING;
29  
30  import java.io.BufferedInputStream;
31  import java.io.ByteArrayInputStream;
32  import java.io.IOException;
33  import java.io.InputStream;
34  import java.io.InputStreamReader;
35  import java.io.Reader;
36  import java.math.BigInteger;
37  import java.util.ArrayList;
38  import java.util.Arrays;
39  import java.util.Collections;
40  import java.util.GregorianCalendar;
41  import java.util.HashMap;
42  import java.util.HashSet;
43  import java.util.List;
44  import java.util.Map;
45  import java.util.Set;
46  
47  import org.apache.chemistry.opencmis.client.api.CmisObject;
48  import org.apache.chemistry.opencmis.client.api.Document;
49  import org.apache.chemistry.opencmis.client.api.FileableCmisObject;
50  import org.apache.chemistry.opencmis.client.api.Folder;
51  import org.apache.chemistry.opencmis.client.api.Item;
52  import org.apache.chemistry.opencmis.client.api.ItemIterable;
53  import org.apache.chemistry.opencmis.client.api.ObjectId;
54  import org.apache.chemistry.opencmis.client.api.ObjectType;
55  import org.apache.chemistry.opencmis.client.api.OperationContext;
56  import org.apache.chemistry.opencmis.client.api.Policy;
57  import org.apache.chemistry.opencmis.client.api.Property;
58  import org.apache.chemistry.opencmis.client.api.Relationship;
59  import org.apache.chemistry.opencmis.client.api.Rendition;
60  import org.apache.chemistry.opencmis.client.api.Session;
61  import org.apache.chemistry.opencmis.client.api.SessionFactory;
62  import org.apache.chemistry.opencmis.client.api.Tree;
63  import org.apache.chemistry.opencmis.client.runtime.OperationContextImpl;
64  import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl;
65  import org.apache.chemistry.opencmis.commons.PropertyIds;
66  import org.apache.chemistry.opencmis.commons.SessionParameter;
67  import org.apache.chemistry.opencmis.commons.data.Ace;
68  import org.apache.chemistry.opencmis.commons.data.Acl;
69  import org.apache.chemistry.opencmis.commons.data.AllowableActions;
70  import org.apache.chemistry.opencmis.commons.data.ContentStream;
71  import org.apache.chemistry.opencmis.commons.data.NewTypeSettableAttributes;
72  import org.apache.chemistry.opencmis.commons.data.ObjectData;
73  import org.apache.chemistry.opencmis.commons.data.ObjectInFolderData;
74  import org.apache.chemistry.opencmis.commons.data.ObjectInFolderList;
75  import org.apache.chemistry.opencmis.commons.data.RepositoryCapabilities;
76  import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
77  import org.apache.chemistry.opencmis.commons.definitions.DocumentTypeDefinition;
78  import org.apache.chemistry.opencmis.commons.definitions.PropertyDecimalDefinition;
79  import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
80  import org.apache.chemistry.opencmis.commons.definitions.PropertyIntegerDefinition;
81  import org.apache.chemistry.opencmis.commons.definitions.PropertyStringDefinition;
82  import org.apache.chemistry.opencmis.commons.definitions.RelationshipTypeDefinition;
83  import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
84  import org.apache.chemistry.opencmis.commons.enums.Action;
85  import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
86  import org.apache.chemistry.opencmis.commons.enums.BindingType;
87  import org.apache.chemistry.opencmis.commons.enums.CapabilityOrderBy;
88  import org.apache.chemistry.opencmis.commons.enums.Cardinality;
89  import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
90  import org.apache.chemistry.opencmis.commons.enums.ContentStreamAllowed;
91  import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
92  import org.apache.chemistry.opencmis.commons.enums.PropertyType;
93  import org.apache.chemistry.opencmis.commons.enums.Updatability;
94  import org.apache.chemistry.opencmis.commons.enums.VersioningState;
95  import org.apache.chemistry.opencmis.commons.exceptions.CmisBaseException;
96  import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
97  import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
98  import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
99  import org.apache.chemistry.opencmis.commons.impl.IOUtils;
100 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl;
101 import org.apache.chemistry.opencmis.tck.CmisTestResult;
102 import org.apache.chemistry.opencmis.tck.CmisTestResultStatus;
103 
104 /**
105  * Base class for tests that require an OpenCMIS session.
106  */
107 public abstract class AbstractSessionTest extends AbstractCmisTest {
108 
109     public static final OperationContext SELECT_ALL_NO_CACHE_OC = new OperationContextImpl();
110     public static final OperationContext SELECT_ALL_NO_CACHE_OC_ORDER_BY_NAME;
111     static {
112         SELECT_ALL_NO_CACHE_OC.setFilterString("*");
113         SELECT_ALL_NO_CACHE_OC.setCacheEnabled(false);
114         SELECT_ALL_NO_CACHE_OC.setIncludeAllowableActions(true);
115         SELECT_ALL_NO_CACHE_OC.setIncludeAcls(true);
116         SELECT_ALL_NO_CACHE_OC.setIncludePathSegments(true);
117         SELECT_ALL_NO_CACHE_OC.setIncludePolicies(true);
118         SELECT_ALL_NO_CACHE_OC.setIncludeRelationships(IncludeRelationships.BOTH);
119         SELECT_ALL_NO_CACHE_OC.setRenditionFilterString("*");
120         SELECT_ALL_NO_CACHE_OC.setOrderBy(null);
121 
122         SELECT_ALL_NO_CACHE_OC_ORDER_BY_NAME = new OperationContextImpl(SELECT_ALL_NO_CACHE_OC);
123         SELECT_ALL_NO_CACHE_OC_ORDER_BY_NAME.setOrderBy("cmis:name");
124     }
125 
126     private final SessionFactory factory = SessionFactoryImpl.newInstance();
127     private Folder testFolder;
128 
129     private Boolean supportsRelationships;
130     private Boolean supportsPolicies;
131     private Boolean supportsItems;
132     private Boolean supportsSecondaries;
133 
134     public BindingType getBinding() {
135         if (getParameters() == null) {
136             return null;
137         }
138 
139         try {
140             return BindingType.fromValue(getParameters().get(SessionParameter.BINDING_TYPE));
141         } catch (Exception e) {
142             return null;
143         }
144     }
145 
146     @Override
147     public String getName() {
148         return super.getName() + " (" + getBinding() + ")";
149     }
150 
151     @Override
152     public void run() throws Exception {
153         Session session;
154 
155         Map<String, String> parameters = getParameters();
156         String repId = parameters.get(SessionParameter.REPOSITORY_ID);
157         if ((repId != null) && (repId.length() > 0)) {
158             session = factory.createSession(parameters);
159         } else {
160             session = factory.getRepositories(parameters).get(0).createSession();
161         }
162 
163         // switch off the cache
164         session.getDefaultContext().setCacheEnabled(false);
165 
166         try {
167             run(session);
168         } catch (Exception e) {
169             if (!(e instanceof FatalTestException)) {
170                 addResult(createResult(UNEXPECTED_EXCEPTION, "Exception: " + e, e, true));
171             }
172         } catch (Error err) {
173             addResult(createResult(UNEXPECTED_EXCEPTION, "Error: " + err, err, true));
174         } finally {
175             testFolder = null;
176         }
177     }
178 
179     public abstract void run(Session session) throws Exception;
180 
181     protected RepositoryInfo getRepositoryInfo(Session session) {
182         RepositoryInfo ri = session.getRepositoryInfo();
183 
184         CmisTestResult failure = createResult(FAILURE, "Repository info is null!", true);
185         addResult(assertNotNull(ri, null, failure));
186 
187         return ri;
188     }
189 
190     protected String getFolderTestTypeId() {
191         String objectTypeId = getParameters().get(TestParameters.DEFAULT_FOLDER_TYPE);
192         if (objectTypeId == null) {
193             objectTypeId = TestParameters.DEFAULT_FOLDER_TYPE_VALUE;
194         }
195 
196         return objectTypeId;
197     }
198 
199     protected String getDocumentTestTypeId() {
200         String objectTypeId = getParameters().get(TestParameters.DEFAULT_DOCUMENT_TYPE);
201         if (objectTypeId == null) {
202             objectTypeId = TestParameters.DEFAULT_DOCUMENT_TYPE_VALUE;
203         }
204 
205         return objectTypeId;
206     }
207 
208     protected String getItemTestTypeId() {
209         String objectTypeId = getParameters().get(TestParameters.DEFAULT_ITEM_TYPE);
210         if (objectTypeId == null) {
211             objectTypeId = TestParameters.DEFAULT_ITEM_TYPE_VALUE;
212         }
213 
214         return objectTypeId;
215     }
216 
217     protected String getSecondaryTestTypeId() {
218         String objectTypeId = getParameters().get(TestParameters.DEFAULT_SECONDARY_TYPE);
219         if (objectTypeId == null) {
220             objectTypeId = TestParameters.DEFAULT_SECONDARY_TYPE_VALUE;
221         }
222 
223         return objectTypeId;
224     }
225 
226     // --- helpers ---
227 
228     protected String[] getAllProperties(CmisObject object) {
229         String[] propertiesk = new String[object.getType().getPropertyDefinitions().size()];
230 
231         int i = 0;
232         for (String propId : object.getType().getPropertyDefinitions().keySet()) {
233             propertiesk[i++] = propId;
234         }
235 
236         return propertiesk;
237     }
238 
239     protected String getStringFromContentStream(ContentStream contentStream) throws IOException {
240         if (contentStream == null || contentStream.getStream() == null) {
241             return null;
242         }
243 
244         StringBuilder sb = new StringBuilder();
245         Reader reader = new InputStreamReader(contentStream.getStream(), IOUtils.UTF8);
246 
247         try {
248             final char[] buffer = new char[64 * 1024];
249             int b;
250             while (true) {
251                 b = reader.read(buffer, 0, buffer.length);
252                 if (b > 0) {
253                     sb.append(buffer, 0, b);
254                 } else if (b == -1) {
255                     break;
256                 }
257             }
258         } finally {
259             reader.close();
260         }
261 
262         return sb.toString();
263     }
264 
265     // --- handy create and delete methods ---
266 
267     /**
268      * Creates a folder.
269      */
270     protected Folder createFolder(Session session, Folder parent, String name) {
271         return createFolder(session, parent, name, getFolderTestTypeId());
272     }
273 
274     /**
275      * Creates a folder.
276      */
277     protected Folder createFolder(Session session, Folder parent, String name, String objectTypeId) {
278         if (parent == null) {
279             throw new IllegalArgumentException("Parent is not set!");
280         }
281         if (name == null) {
282             throw new IllegalArgumentException("Name is not set!");
283         }
284         if (objectTypeId == null) {
285             throw new IllegalArgumentException("Object Type Id is not set!");
286         }
287 
288         // check type
289         ObjectType type;
290         try {
291             type = session.getTypeDefinition(objectTypeId);
292         } catch (CmisObjectNotFoundException e) {
293             addResult(createResult(UNEXPECTED_EXCEPTION,
294                     "Folder type '" + objectTypeId + "' is not available: " + e.getMessage(), e, true));
295             return null;
296         }
297 
298         if (Boolean.FALSE.equals(type.isCreatable())) {
299             addResult(createResult(SKIPPED, "Folder type '" + objectTypeId + "' is not creatable!", true));
300             return null;
301         }
302 
303         // create
304         Map<String, Object> properties = new HashMap<String, Object>();
305         properties.put(PropertyIds.NAME, name);
306         properties.put(PropertyIds.OBJECT_TYPE_ID, objectTypeId);
307 
308         Folder result = null;
309         try {
310             // create the folder
311             result = parent.createFolder(properties, null, null, null, SELECT_ALL_NO_CACHE_OC);
312         } catch (CmisBaseException e) {
313             addResult(createResult(UNEXPECTED_EXCEPTION, "Folder could not be created! Exception: " + e.getMessage(),
314                     e, true));
315             return null;
316         }
317 
318         try {
319             CmisTestResult f;
320 
321             // check folder name
322             f = createResult(FAILURE, "Folder name does not match!", false);
323             addResult(assertEquals(name, result.getName(), null, f));
324 
325             // check the new folder
326             String[] propertiesToCheck = new String[result.getType().getPropertyDefinitions().size()];
327 
328             int i = 0;
329             for (String propId : result.getType().getPropertyDefinitions().keySet()) {
330                 propertiesToCheck[i++] = propId;
331             }
332 
333             addResult(checkObject(session, result, propertiesToCheck, "New folder object spec compliance"));
334 
335             // check object parents
336             List<Folder> objectParents = result.getParents();
337 
338             f = createResult(FAILURE, "Newly created folder has no or more than one parent! Id: " + result.getId(),
339                     true);
340             addResult(assertEquals(1, objectParents.size(), null, f));
341 
342             f = createResult(FAILURE, "First object parent of the newly created folder does not match parent! Id: "
343                     + result.getId(), true);
344             assertShallowEquals(parent, objectParents.get(0), null, f);
345 
346             // check folder parent
347             Folder folderParent = result.getFolderParent();
348             f = createResult(FAILURE, "Newly created folder has no folder parent! Id: " + result.getId(), true);
349             addResult(assertNotNull(folderParent, null, f));
350 
351             f = createResult(FAILURE,
352                     "Folder parent of the newly created folder does not match parent! Id: " + result.getId(), true);
353             assertShallowEquals(parent, folderParent, null, f);
354 
355             // check children of parent
356             boolean found = false;
357             for (CmisObject child : parent.getChildren(SELECT_ALL_NO_CACHE_OC)) {
358                 if (child == null) {
359                     addResult(createResult(FAILURE, "Parent folder contains a null child!", true));
360                 } else {
361                     if (result.getId().equals(child.getId())) {
362                         found = true;
363 
364                         f = createResult(FAILURE, "Folder and parent child don't match! Id: " + result.getId(), true);
365                         assertShallowEquals(result, child, null, f);
366                         break;
367                     }
368                 }
369             }
370 
371             if (!found) {
372                 addResult(createResult(FAILURE, "Folder is not a child of the parent folder! Id: " + result.getId(),
373                         true));
374             }
375         } catch (CmisBaseException e) {
376             addResult(createResult(UNEXPECTED_EXCEPTION,
377                     "Newly created folder is invalid! Exception: " + e.getMessage(), e, true));
378         }
379 
380         return result;
381     }
382 
383     /**
384      * Counts the children in a folder.
385      */
386     protected int countFolderChildren(Folder folder) {
387         int count = 0;
388 
389         for (@SuppressWarnings("unused")
390         CmisObject object : folder.getChildren()) {
391             count++;
392         }
393 
394         return count;
395     }
396 
397     /**
398      * Creates a document.
399      */
400     protected Document createDocument(Session session, Folder parent, String name, String content) {
401         return createDocument(session, parent, name, getDocumentTestTypeId(), null, content);
402     }
403 
404     /**
405      * Creates a document.
406      */
407     protected Document createDocument(Session session, Folder parent, String name, String objectTypeId,
408             String[] secondaryTypeIds, String content) {
409         if (parent == null) {
410             throw new IllegalArgumentException("Parent is not set!");
411         }
412         if (name == null) {
413             throw new IllegalArgumentException("Name is not set!");
414         }
415         if (objectTypeId == null) {
416             throw new IllegalArgumentException("Object Type Id is not set!");
417         }
418 
419         if (content == null) {
420             content = "";
421         }
422 
423         // check type
424         ObjectType type;
425         try {
426             type = session.getTypeDefinition(objectTypeId);
427         } catch (CmisObjectNotFoundException e) {
428             addResult(createResult(UNEXPECTED_EXCEPTION,
429                     "Document type '" + objectTypeId + "' is not available: " + e.getMessage(), e, true));
430             return null;
431         }
432 
433         if (Boolean.FALSE.equals(type.isCreatable())) {
434             addResult(createResult(SKIPPED, "Document type '" + objectTypeId + "' is not creatable!", true));
435             return null;
436         }
437 
438         // create
439         Map<String, Object> properties = new HashMap<String, Object>();
440         properties.put(PropertyIds.NAME, name);
441         properties.put(PropertyIds.OBJECT_TYPE_ID, objectTypeId);
442 
443         if (secondaryTypeIds != null) {
444             properties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, Arrays.asList(secondaryTypeIds));
445         }
446 
447         type = session.getTypeDefinition(objectTypeId);
448         if (!(type instanceof DocumentTypeDefinition)) {
449             addResult(createResult(FAILURE, "Type is not a document type! Type: " + objectTypeId, true));
450             return null;
451         }
452 
453         DocumentTypeDefinition docType = (DocumentTypeDefinition) type;
454         VersioningState versioningState = (Boolean.TRUE.equals(docType.isVersionable()) ? VersioningState.MAJOR
455                 : VersioningState.NONE);
456 
457         byte[] contentBytes = null;
458         Document result = null;
459         try {
460             contentBytes = IOUtils.toUTF8Bytes(content);
461             ContentStream contentStream = new ContentStreamImpl(name, BigInteger.valueOf(contentBytes.length),
462                     "text/plain", new ByteArrayInputStream(contentBytes));
463 
464             // create the document
465             result = parent.createDocument(properties, contentStream, versioningState, null, null, null,
466                     SELECT_ALL_NO_CACHE_OC);
467 
468             contentStream.getStream().close();
469         } catch (Exception e) {
470             addResult(createResult(UNEXPECTED_EXCEPTION, "Document could not be created! Exception: " + e.getMessage(),
471                     e, true));
472             return null;
473         }
474 
475         try {
476             CmisTestResult f;
477 
478             // check document name
479             f = createResult(FAILURE, "Document name does not match!", false);
480             addResult(assertEquals(name, result.getName(), null, f));
481 
482             // check content length
483             f = createResult(WARNING, "Content length does not match!", false);
484             addResult(assertEquals((long) contentBytes.length, result.getContentStreamLength(), null, f));
485 
486             // check the new document
487             addResult(checkObject(session, result, getAllProperties(result), "New document object spec compliance"));
488 
489             // check content
490             try {
491                 ContentStream contentStream = result.getContentStream();
492 
493                 f = createResult(WARNING, "Document filename and the filename of the content stream do not match!",
494                         false);
495                 addResult(assertEquals(name, contentStream.getFileName(), null, f));
496 
497                 f = createResult(WARNING,
498                         "cmis:contentStreamFileName and the filename of the content stream do not match!", false);
499                 addResult(assertEquals(result.getContentStreamFileName(), contentStream.getFileName(), null, f));
500 
501                 String fetchedContent = getStringFromContentStream(result.getContentStream());
502                 if (!content.equals(fetchedContent)) {
503                     addResult(createResult(FAILURE,
504                             "Content of newly created document doesn't match the orign content!"));
505                 }
506             } catch (IOException e) {
507                 addResult(createResult(UNEXPECTED_EXCEPTION,
508                         "Content of newly created document couldn't be read! Exception: " + e.getMessage(), e, true));
509             }
510         } catch (CmisBaseException e) {
511             addResult(createResult(UNEXPECTED_EXCEPTION,
512                     "Newly created document is invalid! Exception: " + e.getMessage(), e, true));
513         }
514 
515         // check parents
516         List<Folder> parents = result.getParents(SELECT_ALL_NO_CACHE_OC);
517         boolean found = false;
518         for (Folder folder : parents) {
519             if (parent.getId().equals(folder.getId())) {
520                 found = true;
521                 break;
522             }
523         }
524 
525         if (!found) {
526             addResult(createResult(FAILURE,
527                     "The folder the document has been created in is not in the list of the document parents!"));
528         }
529 
530         return result;
531     }
532 
533     /**
534      * Creates a relationship.
535      */
536     protected Relationship createRelationship(Session session, String name, ObjectId source, ObjectId target) {
537         String objectTypeId = getParameters().get(TestParameters.DEFAULT_RELATIONSHIP_TYPE);
538         if (objectTypeId == null) {
539             objectTypeId = TestParameters.DEFAULT_RELATIONSHIP_TYPE_VALUE;
540         }
541 
542         return createRelationship(session, name, source, target, objectTypeId);
543     }
544 
545     /**
546      * Creates a relationship.
547      */
548     protected Relationship createRelationship(Session session, String name, ObjectId source, ObjectId target,
549             String objectTypeId) {
550         if (name == null) {
551             throw new IllegalArgumentException("Name is not set!");
552         }
553         if (objectTypeId == null) {
554             throw new IllegalArgumentException("Object Type Id is not set!");
555         }
556 
557         // check type
558         ObjectType type;
559         try {
560             type = session.getTypeDefinition(objectTypeId);
561         } catch (CmisObjectNotFoundException e) {
562             addResult(createResult(UNEXPECTED_EXCEPTION, "Relationship type '" + objectTypeId + "' is not available: "
563                     + e.getMessage(), e, true));
564             return null;
565         }
566 
567         if (Boolean.FALSE.equals(type.isCreatable())) {
568             addResult(createResult(SKIPPED, "Relationship type '" + objectTypeId + "' is not creatable!", true));
569             return null;
570         }
571 
572         // create
573         Map<String, Object> properties = new HashMap<String, Object>();
574         properties.put(PropertyIds.NAME, name);
575         properties.put(PropertyIds.OBJECT_TYPE_ID, objectTypeId);
576         properties.put(PropertyIds.SOURCE_ID, source.getId());
577         properties.put(PropertyIds.TARGET_ID, target.getId());
578 
579         ObjectId relId;
580         Relationship result = null;
581 
582         try {
583             relId = session.createRelationship(properties);
584             result = (Relationship) session.getObject(relId, SELECT_ALL_NO_CACHE_OC);
585         } catch (Exception e) {
586             addResult(createResult(UNEXPECTED_EXCEPTION,
587                     "Relationship could not be created! Exception: " + e.getMessage(), e, true));
588         }
589 
590         if (result != null) {
591             try {
592                 // check the new relationship
593                 addResult(checkObject(session, result, getAllProperties(result), "New document object spec compliance"));
594             } catch (CmisBaseException e) {
595                 addResult(createResult(UNEXPECTED_EXCEPTION,
596                         "Newly created document is invalid! Exception: " + e.getMessage(), e, true));
597             }
598         }
599 
600         return result;
601     }
602 
603     /**
604      * Creates a item.
605      */
606     protected Item createItem(Session session, Folder parent, String name) {
607         return createItem(session, parent, name, getItemTestTypeId());
608     }
609 
610     /**
611      * Creates a item.
612      */
613     protected Item createItem(Session session, Folder parent, String name, String objectTypeId) {
614         if (parent == null) {
615             throw new IllegalArgumentException("Parent is not set!");
616         }
617         if (name == null) {
618             throw new IllegalArgumentException("Name is not set!");
619         }
620         if (objectTypeId == null) {
621             throw new IllegalArgumentException("Object Type Id is not set!");
622         }
623 
624         // check type
625         ObjectType type;
626         try {
627             type = session.getTypeDefinition(objectTypeId);
628         } catch (CmisObjectNotFoundException e) {
629             addResult(createResult(UNEXPECTED_EXCEPTION,
630                     "Item type '" + objectTypeId + "' is not available: " + e.getMessage(), e, true));
631             return null;
632         }
633 
634         if (Boolean.FALSE.equals(type.isCreatable())) {
635             addResult(createResult(SKIPPED, "Item type '" + objectTypeId + "' is not creatable!", true));
636             return null;
637         }
638 
639         // create
640         Map<String, Object> properties = new HashMap<String, Object>();
641         properties.put(PropertyIds.NAME, name);
642         properties.put(PropertyIds.OBJECT_TYPE_ID, objectTypeId);
643 
644         Item result = null;
645         try {
646             // create the item
647             result = parent.createItem(properties, null, null, null, SELECT_ALL_NO_CACHE_OC);
648         } catch (CmisBaseException e) {
649             addResult(createResult(UNEXPECTED_EXCEPTION, "Item could not be created! Exception: " + e.getMessage(), e,
650                     true));
651             return null;
652         }
653 
654         try {
655             CmisTestResult f;
656 
657             // check item name
658             f = createResult(FAILURE, "Item name does not match!", false);
659             addResult(assertEquals(name, result.getName(), null, f));
660 
661             addResult(checkObject(session, result, getAllProperties(result), "New item object spec compliance"));
662         } catch (CmisBaseException e) {
663             addResult(createResult(UNEXPECTED_EXCEPTION, "Newly created Item is invalid! Exception: " + e.getMessage(),
664                     e, true));
665         }
666 
667         // check parents
668         List<Folder> parents = result.getParents(SELECT_ALL_NO_CACHE_OC);
669         boolean found = false;
670         for (Folder folder : parents) {
671             if (parent.getId().equals(folder.getId())) {
672                 found = true;
673                 break;
674             }
675         }
676 
677         if (!found) {
678             addResult(createResult(FAILURE,
679                     "The folder the item has been created in is not in the list of the item parents!"));
680         }
681 
682         return result;
683     }
684 
685     /**
686      * Deletes an object and checks if it is deleted.
687      */
688     protected void deleteObject(CmisObject object) {
689         if (object != null) {
690             if (object instanceof Folder) {
691                 try {
692                     ((Folder) object).deleteTree(true, null, true);
693                 } catch (CmisBaseException e) {
694                     addResult(createResult(UNEXPECTED_EXCEPTION,
695                             "Folder could not be deleted! Exception: " + e.getMessage(), e, true));
696                 }
697             } else {
698                 try {
699                     object.delete(true);
700                 } catch (CmisBaseException e) {
701                     addResult(createResult(UNEXPECTED_EXCEPTION,
702                             "Object could not be deleted! Exception: " + e.getMessage(), e, true));
703                 }
704             }
705 
706             CmisTestResult f = createResult(FAILURE, "Object should not exist anymore but it is still there! Id: "
707                     + object.getId(), true);
708             addResult(assertIsFalse(exists(object), null, f));
709         }
710     }
711 
712     /**
713      * Tests if an object exists by refreshing it.
714      */
715     protected boolean exists(CmisObject object) {
716         try {
717             object.refresh();
718             return true;
719         } catch (CmisObjectNotFoundException e) {
720             return false;
721         }
722     }
723 
724     // --- type helpers ---
725 
726     /**
727      * Creates a new type.
728      */
729     protected ObjectType createType(Session session, TypeDefinition typeDef) {
730 
731         NewTypeSettableAttributes settableAttributes = session.getRepositoryInfo().getCapabilities()
732                 .getNewTypeSettableAttributes();
733         if (settableAttributes == null) {
734             addResult(createResult(WARNING, "Repository Info does not indicate, which type attributes can be set!"));
735         } else {
736             // TODO: add more tests
737         }
738 
739         ObjectType newType = null;
740         try {
741             newType = session.createType(typeDef);
742             addResult(createInfoResult("Created type '" + typeDef.getId()
743                     + "'. Repository assigned the following type id: " + newType.getId()));
744         } catch (CmisBaseException e) {
745             addResult(createResult(FAILURE, "Creating type '" + typeDef.getId() + "' failed: " + e.getMessage(), e,
746                     false));
747             return null;
748         }
749 
750         addResult(checkTypeDefinition(session, newType, "Newly created type spec compliance."));
751 
752         if (newType.getTypeMutability() == null) {
753             addResult(createResult(FAILURE,
754                     "Newly created type does not provide type mutability data! Id: " + newType.getId()));
755         }
756 
757         return newType;
758     }
759 
760     /**
761      * Deletes a type.
762      */
763     protected void deleteType(Session session, String typeId) {
764         ObjectType type = session.getTypeDefinition(typeId);
765 
766         if (type == null) {
767             addResult(createResult(FAILURE, "Type does not exist and therefore cannot be deleted! Id: " + typeId));
768             return;
769         }
770 
771         // check if type can be deleted
772         if (type.getTypeMutability() == null) {
773             addResult(createResult(FAILURE, "Type does not provide type mutability data! Id: " + typeId));
774         } else {
775             if (!Boolean.TRUE.equals(type.getTypeMutability().canDelete())) {
776                 addResult(createResult(WARNING, "Type indicates that it cannot be deleted. Trying it anyway. Id: "
777                         + typeId));
778             }
779         }
780 
781         // delete it
782         try {
783             session.deleteType(typeId);
784         } catch (CmisBaseException e) {
785             addResult(createResult(FAILURE, "Deleting type '" + typeId + "' failed: " + e.getMessage(), e, false));
786             return;
787         }
788 
789         // check if the type still exists
790         try {
791             session.getTypeDefinition(typeId);
792             addResult(createResult(FAILURE, "Type should not exist anymore but it is still there! Id: " + typeId, true));
793         } catch (CmisObjectNotFoundException e) {
794             // expected result
795         }
796     }
797 
798     // --- test folder methods ---
799 
800     /**
801      * Creates a test folder.
802      */
803     protected Folder createTestFolder(Session session) {
804 
805         String testFolderParentPath = getParameters().get(TestParameters.DEFAULT_TEST_FOLDER_PARENT);
806         if (testFolderParentPath == null) {
807             testFolderParentPath = TestParameters.DEFAULT_TEST_FOLDER_PARENT_VALUE;
808         }
809 
810         String name = "cmistck" + System.currentTimeMillis() + session.getRepositoryInfo().hashCode();
811 
812         Folder parent = null;
813         try {
814             CmisObject parentObject = session.getObjectByPath(testFolderParentPath, SELECT_ALL_NO_CACHE_OC);
815             if (!(parentObject instanceof Folder)) {
816                 addResult(createResult(FAILURE, "Parent folder of the test folder is actually not a folder! Path: "
817                         + testFolderParentPath, true));
818             }
819 
820             parent = (Folder) parentObject;
821         } catch (CmisBaseException e) {
822             addResult(createResult(UNEXPECTED_EXCEPTION,
823                     "Test folder could not be created! Exception: " + e.getMessage(), e, true));
824         }
825 
826         if (parent != null) {
827             testFolder = createFolder(session, parent, name);
828         }
829 
830         return testFolder;
831     }
832 
833     /**
834      * Get the test folder.
835      */
836     protected Folder getTestFolder() {
837         return testFolder;
838     }
839 
840     /**
841      * Delete the test folder.
842      */
843     protected void deleteTestFolder() {
844         deleteObject(testFolder);
845     }
846 
847     // --- reusable checks ----
848 
849     protected boolean isGetDescendantsSupported(Session session) {
850         RepositoryCapabilities cap = session.getRepositoryInfo().getCapabilities();
851 
852         if (cap == null) {
853             return false;
854         }
855 
856         if (cap.isGetDescendantsSupported() == null) {
857             return false;
858         }
859 
860         return cap.isGetDescendantsSupported().booleanValue();
861     }
862 
863     protected boolean isGetFolderTreeSupported(Session session) {
864         RepositoryCapabilities cap = session.getRepositoryInfo().getCapabilities();
865 
866         if (cap == null) {
867             return false;
868         }
869 
870         if (cap.isGetFolderTreeSupported() == null) {
871             return false;
872         }
873 
874         return cap.isGetFolderTreeSupported().booleanValue();
875     }
876 
877     protected boolean isOrderByNameSupported(Session session) {
878         if (session.getRepositoryInfo().getCapabilities().getOrderByCapability() == CapabilityOrderBy.NONE) {
879             return false;
880         }
881 
882         return true;
883     }
884 
885     protected boolean hasRelationships(Session session) {
886         if (supportsRelationships == null) {
887             supportsRelationships = Boolean.FALSE;
888             for (ObjectType type : session.getTypeChildren(null, false)) {
889                 if (BaseTypeId.CMIS_RELATIONSHIP.value().equals(type.getId())) {
890                     supportsRelationships = Boolean.TRUE;
891                     break;
892                 }
893             }
894         }
895 
896         return supportsRelationships.booleanValue();
897     }
898 
899     protected boolean hasPolicies(Session session) {
900         if (supportsPolicies == null) {
901             supportsPolicies = Boolean.FALSE;
902             for (ObjectType type : session.getTypeChildren(null, false)) {
903                 if (BaseTypeId.CMIS_POLICY.value().equals(type.getId())) {
904                     supportsPolicies = Boolean.TRUE;
905                     break;
906                 }
907             }
908         }
909 
910         return supportsPolicies.booleanValue();
911     }
912 
913     protected boolean hasItems(Session session) {
914         if (supportsItems == null) {
915             supportsItems = Boolean.FALSE;
916             for (ObjectType type : session.getTypeChildren(null, false)) {
917                 if (BaseTypeId.CMIS_ITEM.value().equals(type.getId())) {
918                     supportsItems = Boolean.TRUE;
919                     break;
920                 }
921             }
922         }
923 
924         return supportsItems.booleanValue();
925     }
926 
927     protected boolean hasSecondaries(Session session) {
928         if (supportsSecondaries == null) {
929             supportsSecondaries = Boolean.FALSE;
930             for (ObjectType type : session.getTypeChildren(null, false)) {
931                 if (BaseTypeId.CMIS_SECONDARY.value().equals(type.getId())) {
932                     supportsSecondaries = Boolean.TRUE;
933                     break;
934                 }
935             }
936         }
937 
938         return supportsSecondaries.booleanValue();
939     }
940 
941     protected CmisTestResult checkObject(Session session, CmisObject object, String[] properties, String message) {
942         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
943 
944         CmisTestResult f;
945 
946         f = createResult(FAILURE, "Object is null!", true);
947         addResult(results, assertNotNull(object, null, f));
948 
949         if (object != null) {
950             f = createResult(FAILURE, "Object id is not set!");
951             addResult(results, assertStringNotEmpty(object.getId(), null, f));
952 
953             GregorianCalendar creationDate = null;
954             GregorianCalendar lastModificationDate = null;
955 
956             // properties
957             for (String propId : properties) {
958                 Property<?> prop = object.getProperty(propId);
959 
960                 // values of non-spec properties are not checked here
961                 PropertyCheckEnum propertyCheck = PropertyCheckEnum.NO_VALUE_CHECK;
962 
963                 // known properties that are strings and must be set
964                 if (PropertyIds.OBJECT_ID.equals(propId) || PropertyIds.BASE_TYPE_ID.equals(propId)
965                         || PropertyIds.OBJECT_TYPE_ID.equals(propId) || PropertyIds.PATH.equals(propId)
966                         || PropertyIds.SOURCE_ID.equals(propId) || PropertyIds.TARGET_ID.equals(propId)) {
967                     propertyCheck = PropertyCheckEnum.STRING_MUST_NOT_BE_EMPTY;
968                 }
969 
970                 if (!(object instanceof Relationship)) {
971                     if (PropertyIds.CREATED_BY.equals(propId) || PropertyIds.LAST_MODIFIED_BY.equals(propId)) {
972                         propertyCheck = PropertyCheckEnum.STRING_MUST_NOT_BE_EMPTY;
973                     }
974                 }
975 
976                 // known properties that are strings and should be set
977                 if (PropertyIds.NAME.equals(propId) || PropertyIds.POLICY_TEXT.equals(propId)) {
978                     propertyCheck = PropertyCheckEnum.STRING_SHOULD_NOT_BE_EMPTY;
979                 }
980 
981                 // known properties that are not strings and must be set
982                 if (PropertyIds.IS_IMMUTABLE.equals(propId)) {
983                     propertyCheck = PropertyCheckEnum.MUST_BE_SET;
984                 }
985 
986                 if (!(object instanceof Relationship)) {
987                     if (PropertyIds.CREATION_DATE.equals(propId) || PropertyIds.LAST_MODIFICATION_DATE.equals(propId)) {
988                         propertyCheck = PropertyCheckEnum.MUST_BE_SET;
989                     }
990                 }
991 
992                 // special case: parent
993                 if (PropertyIds.PARENT_ID.equals(propId)) {
994                     if (object instanceof Folder) {
995                         if (((Folder) object).isRootFolder()) {
996                             propertyCheck = PropertyCheckEnum.MUST_NOT_BE_SET;
997                         } else {
998                             propertyCheck = PropertyCheckEnum.STRING_MUST_NOT_BE_EMPTY;
999                         }
1000                     } else {
1001                         addResult(
1002                                 results,
1003                                 createResult(FAILURE, "Property " + PropertyIds.PARENT_ID
1004                                         + " is only defined for folders!"));
1005                     }
1006                 }
1007 
1008                 // special case: path
1009                 if (PropertyIds.PATH.equals(propId) && prop.getFirstValue() != null) {
1010                     Object path = prop.getFirstValue();
1011                     if (path instanceof String) {
1012                         f = createResult(FAILURE, "Path does not start with '/': " + path);
1013                         addResult(results,
1014                                 assertIsTrue(((String) path).length() > 0 && ((String) path).charAt(0) == '/', null, f));
1015                     } else {
1016                         addResult(results, createResult(FAILURE, "Property " + PropertyIds.PATH + " is not a string!"));
1017                     }
1018                 }
1019 
1020                 // check property
1021                 addResult(results, checkProperty(prop, "Property " + propId, propertyCheck));
1022 
1023                 // catch creationDate and lastModificationDate
1024                 if (PropertyIds.CREATION_DATE.equals(propId)) {
1025                     creationDate = (GregorianCalendar) prop.getFirstValue();
1026                 } else if (PropertyIds.LAST_MODIFICATION_DATE.equals(propId)) {
1027                     lastModificationDate = (GregorianCalendar) prop.getFirstValue();
1028                 }
1029             }
1030 
1031             // check creationDate <= lastModificationDate
1032             if (creationDate != null && lastModificationDate != null) {
1033                 f = createResult(FAILURE, "Last modification date precedes creation date!");
1034                 addResult(results,
1035                         assertIsTrue(creationDate.getTimeInMillis() <= lastModificationDate.getTimeInMillis(), null, f));
1036 
1037                 f = createResult(WARNING, "Creation date and last modification date have different timezones.");
1038                 addResult(assertIsTrue(creationDate.getTimeZone().hasSameRules(lastModificationDate.getTimeZone()),
1039                         null, f));
1040             }
1041 
1042             // allowable actions
1043             if ((object.getAllowableActions() == null) || (object.getAllowableActions().getAllowableActions() == null)) {
1044                 addResult(results, createResult(FAILURE, "Object has no allowable actions!"));
1045             } else {
1046                 Set<Action> actions = object.getAllowableActions().getAllowableActions();
1047 
1048                 f = createResult(FAILURE, "Object has no CAN_GET_PROPERTIES allowable action!");
1049                 addResult(results, assertAllowableAction(object, Action.CAN_GET_PROPERTIES, null, f));
1050                 addResult(results, assertIsTrue(object.hasAllowableAction(Action.CAN_GET_PROPERTIES), null, f));
1051 
1052                 if (object instanceof Document) {
1053                     if (actions.contains(Action.CAN_CHECK_OUT) && actions.contains(Action.CAN_CHECK_IN)) {
1054                         addResult(
1055                                 results,
1056                                 createResult(FAILURE,
1057                                         "Document object has CAN_CHECK_OUT and CAN_CHECK_IN allowable actions!"));
1058                     }
1059 
1060                     if (actions.contains(Action.CAN_CHECK_OUT) && actions.contains(Action.CAN_CANCEL_CHECK_OUT)) {
1061                         addResult(
1062                                 results,
1063                                 createResult(FAILURE,
1064                                         "Document object has CAN_CHECK_OUT and CAN_CANCEL_CHECK_OUT allowable actions!"));
1065                     }
1066 
1067                     Document doc = (Document) object;
1068                     DocumentTypeDefinition docType = (DocumentTypeDefinition) doc.getType();
1069                     if (doc.isVersionSeriesCheckedOut() != null) {
1070                         if (doc.isVersionSeriesCheckedOut()) {
1071                             f = createResult(WARNING, "Document is checked out and has CAN_CHECK_OUT allowable action!");
1072                             addResult(results, assertNotAllowableAction(object, Action.CAN_CHECK_OUT, null, f));
1073 
1074                             if (doc.getVersionSeriesCheckedOutId() == null) {
1075                                 addResult(
1076                                         results,
1077                                         createResult(WARNING,
1078                                                 "Document is checked out and but the property cmis:versionSeriesCheckedOutId is not set!"));
1079                             } else {
1080                                 if (doc.getVersionSeriesCheckedOutId().equals(object.getId())) {
1081                                     // object is PWC
1082                                     f = createResult(FAILURE, "PWC doesn't have CAN_CHECK_IN allowable action!");
1083                                     addResult(results, assertAllowableAction(object, Action.CAN_CHECK_IN, null, f));
1084 
1085                                     f = createResult(FAILURE, "PWC doesn't have CAN_CANCEL_CHECK_OUT allowable action!");
1086                                     addResult(results,
1087                                             assertAllowableAction(object, Action.CAN_CANCEL_CHECK_OUT, null, f));
1088                                 } else {
1089                                     // object is not PWC
1090                                     f = createResult(WARNING, "Non-PWC has CAN_CHECK_IN allowable action!");
1091                                     addResult(results, assertNotAllowableAction(object, Action.CAN_CHECK_IN, null, f));
1092 
1093                                     f = createResult(WARNING, "Non-PWC has CAN_CANCEL_CHECK_OUT allowable action!");
1094                                     addResult(results,
1095                                             assertNotAllowableAction(object, Action.CAN_CANCEL_CHECK_OUT, null, f));
1096                                 }
1097                             }
1098                         } else {
1099                             f = createResult(FAILURE,
1100                                     "Document is not checked out and has CAN_CHECK_IN allowable action!");
1101                             addResult(results, assertNotAllowableAction(object, Action.CAN_CHECK_IN, null, f));
1102 
1103                             f = createResult(FAILURE,
1104                                     "Document is not checked out and has CAN_CANCEL_CHECK_OUT allowable action!");
1105                             addResult(results, assertNotAllowableAction(object, Action.CAN_CANCEL_CHECK_OUT, null, f));
1106 
1107                             // versionable check
1108                             if (docType.isVersionable()) {
1109                                 if (Boolean.TRUE.equals(doc.isLatestVersion())) {
1110                                     f = createResult(WARNING,
1111                                             "Document is versionable and not checked but has no CAN_CHECK_OUT allowable action!");
1112                                     addResult(results, assertAllowableAction(object, Action.CAN_CHECK_OUT, null, f));
1113                                 }
1114                             } else {
1115                                 f = createResult(FAILURE,
1116                                         "Document is not versionable but has CAN_CHECK_OUT allowable action!");
1117                                 addResult(results, assertNotAllowableAction(object, Action.CAN_CHECK_OUT, null, f));
1118                             }
1119                         }
1120                     } else {
1121                         addResult(results, createResult(WARNING, "Property cmis:isVersionSeriesCheckedOut is not set!"));
1122                     }
1123 
1124                     // immutable check
1125                     if (Boolean.TRUE.equals(doc.isImmutable())) {
1126                         f = createResult(FAILURE,
1127                                 "Document is immutable and has CAN_UPDATE_PROPERTIES allowable action!");
1128                         addResult(results, assertNotAllowableAction(object, Action.CAN_UPDATE_PROPERTIES, null, f));
1129 
1130                         f = createResult(FAILURE, "Document is immutable and has CAN_DELETE_OBJECT allowable action!");
1131                         addResult(results, assertNotAllowableAction(object, Action.CAN_DELETE_OBJECT, null, f));
1132                     }
1133                 } else {
1134                     f = createResult(FAILURE, "Non-Document object has CAN_CHECK_IN allowable action!");
1135                     addResult(results, assertNotAllowableAction(object, Action.CAN_CHECK_IN, null, f));
1136 
1137                     f = createResult(FAILURE, "Non-Document object has CAN_CHECK_OUT allowable action!");
1138                     addResult(results, assertNotAllowableAction(object, Action.CAN_CHECK_OUT, null, f));
1139 
1140                     f = createResult(FAILURE, "Non-Document object has CAN_CANCEL_CHECK_OUT allowable action!");
1141                     addResult(results, assertNotAllowableAction(object, Action.CAN_CANCEL_CHECK_OUT, null, f));
1142 
1143                     f = createResult(FAILURE, "Non-Document object has CAN_GET_CONTENT_STREAM allowable action!");
1144                     addResult(results, assertNotAllowableAction(object, Action.CAN_GET_CONTENT_STREAM, null, f));
1145 
1146                     f = createResult(FAILURE, "Non-Document object has CAN_DELETE_CONTENT_STREAM allowable action!");
1147                     addResult(results, assertNotAllowableAction(object, Action.CAN_DELETE_CONTENT_STREAM, null, f));
1148 
1149                     f = createResult(FAILURE, "Non-Document object has CAN_GET_ALL_VERSIONS allowable action!");
1150                     addResult(results, assertNotAllowableAction(object, Action.CAN_GET_ALL_VERSIONS, null, f));
1151                 }
1152 
1153                 if (object instanceof Folder) {
1154                     Folder folder = (Folder) object;
1155                     if (folder.isRootFolder()) {
1156                         f = createResult(FAILURE, "Root folder has CAN_DELETE_OBJECT allowable action!");
1157                         addResult(results, assertNotAllowableAction(object, Action.CAN_DELETE_OBJECT, null, f));
1158 
1159                         f = createResult(FAILURE, "Root folder has CAN_GET_FOLDER_PARENT allowable action!");
1160                         addResult(results, assertNotAllowableAction(object, Action.CAN_GET_FOLDER_PARENT, null, f));
1161 
1162                         f = createResult(FAILURE, "Root folder has CAN_MOVE_OBJECT allowable action!");
1163                         addResult(results, assertNotAllowableAction(object, Action.CAN_MOVE_OBJECT, null, f));
1164                     }
1165                 } else {
1166                     f = createResult(FAILURE, "Non-Folder object has CAN_GET_DESCENDANTS allowable action!");
1167                     addResult(results, assertNotAllowableAction(object, Action.CAN_GET_DESCENDANTS, null, f));
1168 
1169                     f = createResult(FAILURE, "Non-Folder object has CAN_GET_FOLDER_PARENT allowable action!");
1170                     addResult(results, assertNotAllowableAction(object, Action.CAN_GET_FOLDER_PARENT, null, f));
1171 
1172                     f = createResult(FAILURE, "Non-Folder object has CAN_GET_CHILDREN allowable action!");
1173                     addResult(results, assertNotAllowableAction(object, Action.CAN_GET_CHILDREN, null, f));
1174 
1175                     f = createResult(FAILURE, "Non-Folder object has CAN_DELETE_TREE allowable action!");
1176                     addResult(results, assertNotAllowableAction(object, Action.CAN_DELETE_TREE, null, f));
1177 
1178                     f = createResult(FAILURE, "Non-Folder object has CAN_GET_FOLDER_PARENT allowable action!");
1179                     addResult(results, assertNotAllowableAction(object, Action.CAN_GET_FOLDER_PARENT, null, f));
1180 
1181                     f = createResult(FAILURE, "Non-Folder object has CAN_CREATE_DOCUMENT allowable action!");
1182                     addResult(results, assertNotAllowableAction(object, Action.CAN_CREATE_DOCUMENT, null, f));
1183 
1184                     f = createResult(FAILURE, "Non-Folder object has CAN_CREATE_FOLDER allowable action!");
1185                     addResult(results, assertNotAllowableAction(object, Action.CAN_CREATE_FOLDER, null, f));
1186                 }
1187 
1188                 if (!(object instanceof FileableCmisObject) || (object instanceof Folder)) {
1189                     f = createResult(FAILURE,
1190                             "Non-Filable object or folder has CAN_ADD_OBJECT_TO_FOLDER allowable action!");
1191                     addResult(results, assertNotAllowableAction(object, Action.CAN_ADD_OBJECT_TO_FOLDER, null, f));
1192 
1193                     f = createResult(FAILURE,
1194                             "Non-Filable object or folder has CAN_REMOVE_OBJECT_FROM_FOLDER allowable action!");
1195                     addResult(results, assertNotAllowableAction(object, Action.CAN_REMOVE_OBJECT_FROM_FOLDER, null, f));
1196                 }
1197 
1198                 if (!(object instanceof FileableCmisObject)) {
1199                     f = createResult(FAILURE, "Non-Fileable object has CAN_MOVE_OBJECT allowable action!");
1200                     addResult(results, assertNotAllowableAction(object, Action.CAN_MOVE_OBJECT, null, f));
1201                 }
1202 
1203                 // get allowable actions again
1204                 AllowableActions allowableActions = session.getBinding().getObjectService()
1205                         .getAllowableActions(session.getRepositoryInfo().getId(), object.getId(), null);
1206 
1207                 if (allowableActions.getAllowableActions() == null) {
1208                     addResult(results,
1209                             createResult(FAILURE, "getAllowableActions() didn't returned allowable actions!"));
1210                 } else {
1211                     f = createResult(FAILURE,
1212                             "Object allowable actions don't match the allowable actions returned by getAllowableActions()!");
1213                     addResult(
1214                             results,
1215                             assertEqualSet(object.getAllowableActions().getAllowableActions(),
1216                                     allowableActions.getAllowableActions(), null, f));
1217                 }
1218             }
1219 
1220             // check ACL
1221             if (object.getAcl() != null && object.getAcl().getAces() != null) {
1222                 addResult(results, checkACL(session, object.getAcl(), true, "ACL"));
1223             }
1224 
1225             // check policies
1226             if (hasPolicies(session)) {
1227                 try {
1228                     List<ObjectData> appliedPolicies = session.getBinding().getPolicyService()
1229                             .getAppliedPolicies(session.getRepositoryInfo().getId(), object.getId(), "*", null);
1230 
1231                     if (appliedPolicies == null) {
1232                         appliedPolicies = Collections.emptyList();
1233                     }
1234 
1235                     List<Policy> objectPolicies = object.getPolicies();
1236                     if (objectPolicies == null) {
1237                         objectPolicies = Collections.emptyList();
1238                     }
1239 
1240                     f = createResult(FAILURE,
1241                             "The number of policies returned by getAppliedPolicies() and the number of object policies don't match!");
1242                     addResult(results, assertEquals(appliedPolicies.size(), objectPolicies.size(), null, f));
1243                 } catch (CmisNotSupportedException e) {
1244                     addResult(results,
1245                             createResult(WARNING, "getAppliedPolicies() not supported for object: " + object.getId()));
1246                 }
1247             }
1248 
1249             // check relationships
1250             checkRelationships(session, results, object);
1251 
1252             // check document content
1253             checkDocumentContent(session, results, object);
1254 
1255             // check renditions
1256             if (object.getRenditions() != null) {
1257                 addResult(results, checkRenditions(session, object, "Rendition check"));
1258             }
1259 
1260             // check allowed child object type ids
1261             if (object instanceof Folder) {
1262                 List<String> otids = object.getPropertyValue(PropertyIds.ALLOWED_CHILD_OBJECT_TYPE_IDS);
1263                 if (otids != null) {
1264                     for (String otid : otids) {
1265                         try {
1266                             session.getTypeDefinition(otid);
1267                         } catch (CmisBaseException e) {
1268                             addResult(
1269                                     results,
1270                                     createResult(FAILURE,
1271                                             "The cmis:allowedChildObjectTypeIds property contains the type id '" + otid
1272                                                     + "' but the type doesn't exists. Folder id: " + object.getId()));
1273                         }
1274                     }
1275                 }
1276             }
1277 
1278             // check path
1279             if (object instanceof FileableCmisObject) {
1280                 List<String> paths = ((FileableCmisObject) object).getPaths();
1281                 if (object instanceof Folder) {
1282                     f = createResult(FAILURE, "Folder does not have excatly one path! This is an OpenCMIS bug!");
1283                     addResult(results, assertEquals(1, paths.size(), null, f));
1284                 } else {
1285                     if (Boolean.FALSE.equals(session.getRepositoryInfo().getCapabilities().isMultifilingSupported())) {
1286                         f = createResult(FAILURE,
1287                                 "Repository does not support multi-filing, but the object has more than one parent!");
1288                         addResult(results, assertIsTrue(paths.size() < 2, null, f));
1289                     }
1290                 }
1291             }
1292         }
1293 
1294         CmisTestResultImpl result = createResult(getWorst(results), message);
1295         result.getChildren().addAll(results);
1296 
1297         return (result.getStatus().getLevel() <= OK.getLevel() ? null : result);
1298     }
1299 
1300     protected CmisTestResult checkACL(Session session, Acl acl, boolean checkExact, String message) {
1301         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
1302 
1303         CmisTestResult f;
1304 
1305         f = createResult(FAILURE, "ACL is null!");
1306         addResult(results, assertNotNull(acl, null, f));
1307 
1308         if (acl != null) {
1309 
1310             f = createResult(FAILURE, "List of ACEs is null!");
1311             addResult(results, assertNotNull(acl.getAces(), null, f));
1312 
1313             if (acl.getAces() != null) {
1314                 for (Ace ace : acl.getAces()) {
1315                     f = createResult(FAILURE, "ACE with empty principal ID!");
1316                     addResult(results, assertStringNotEmpty(ace.getPrincipalId(), null, f));
1317 
1318                     f = createResult(FAILURE, "ACE with empty permission list!");
1319                     addResult(results, assertListNotEmpty(ace.getPermissions(), null, f));
1320 
1321                     if (ace.getPermissions() != null) {
1322                         for (String permission : ace.getPermissions()) {
1323                             f = createResult(FAILURE, "ACE with empty permission entry!");
1324                             addResult(results, assertStringNotEmpty(permission, null, f));
1325                         }
1326                     }
1327                 }
1328             }
1329 
1330             if (checkExact) {
1331                 f = createResult(FAILURE, "ACL is provided but the isExact flag is not set!");
1332                 addResult(results, assertNotNull(acl.isExact(), null, f));
1333             }
1334         }
1335 
1336         CmisTestResultImpl result = createResult(getWorst(results), message);
1337         result.getChildren().addAll(results);
1338 
1339         return (result.getStatus().getLevel() <= OK.getLevel() ? null : result);
1340     }
1341 
1342     private void checkRelationships(Session session, List<CmisTestResult> results, CmisObject object) {
1343         if (object instanceof Relationship) {
1344             if (isNotEmpty(object.getRelationships())) {
1345                 addResult(results, createResult(FAILURE, "A relationship has relationships!"));
1346                 return;
1347             }
1348         }
1349 
1350         if (object.getRelationships() != null) {
1351             for (Relationship relationship : object.getRelationships()) {
1352                 if (relationship == null) {
1353                     addResult(results, createResult(FAILURE, "A relationship in the relationship list is null!"));
1354                     continue;
1355                 }
1356 
1357                 CmisObject fullRelationshipObject = session.getObject(relationship, SELECT_ALL_NO_CACHE_OC);
1358                 addResult(
1359                         results,
1360                         checkObject(session, fullRelationshipObject, getAllProperties(fullRelationshipObject),
1361                                 "Relationship check: " + fullRelationshipObject.getId()));
1362             }
1363         }
1364     }
1365 
1366     private void checkDocumentContent(Session session, List<CmisTestResult> results, CmisObject object) {
1367         if (!(object instanceof Document)) {
1368             // only documents have content
1369             return;
1370         }
1371 
1372         CmisTestResult f;
1373 
1374         Document doc = (Document) object;
1375         DocumentTypeDefinition type = (DocumentTypeDefinition) doc.getType();
1376 
1377         // check ContentStreamAllowed flag
1378         boolean hasContentProperties = (doc.getContentStreamFileName() != null) || (doc.getContentStreamId() != null)
1379                 || (doc.getContentStreamLength() > -1) || (doc.getContentStreamMimeType() != null);
1380 
1381         if (hasContentProperties) {
1382             if (type.getContentStreamAllowed() == ContentStreamAllowed.NOTALLOWED) {
1383                 addResult(
1384                         results,
1385                         createResult(FAILURE,
1386                                 "Content properties have values but the document type doesn't allow content!"));
1387             }
1388         } else {
1389             if (type.getContentStreamAllowed() == ContentStreamAllowed.REQUIRED) {
1390                 addResult(results,
1391                         createResult(FAILURE, "Content properties are not set but the document type demands content!"));
1392             }
1393         }
1394 
1395         // get the content stream
1396         ContentStream contentStream = doc.getContentStream();
1397 
1398         if (contentStream == null) {
1399             if (hasContentProperties && doc.getContentStreamLength() > 0) {
1400                 addResult(results,
1401                         createResult(FAILURE, "Content properties have values but the document has no content!"));
1402             }
1403 
1404             if (type.getContentStreamAllowed() == ContentStreamAllowed.REQUIRED) {
1405                 addResult(results,
1406                         createResult(FAILURE, "The document type demands content but the document has no content!"));
1407             }
1408 
1409             return;
1410         }
1411 
1412         if (type.getContentStreamAllowed() == ContentStreamAllowed.NOTALLOWED) {
1413             addResult(results, createResult(FAILURE, "Document type doesn't allow content but document has content!"));
1414         }
1415 
1416         // file name check
1417         f = createResult(FAILURE, "Content file names don't match!");
1418         addResult(results, assertEquals(doc.getContentStreamFileName(), contentStream.getFileName(), null, f));
1419 
1420         if (doc.getContentStreamLength() > -1 && contentStream.getLength() > -1) {
1421             f = createResult(FAILURE, "Content lengths don't match!");
1422             addResult(results, assertEquals(doc.getContentStreamLength(), contentStream.getLength(), null, f));
1423         }
1424 
1425         // MIME type check
1426         String docMimeType = doc.getContentStreamMimeType();
1427         if (docMimeType != null) {
1428             int x = docMimeType.indexOf(';');
1429             if (x > -1) {
1430                 docMimeType = docMimeType.substring(0, x);
1431             }
1432             docMimeType = docMimeType.trim();
1433         }
1434 
1435         String contentMimeType = contentStream.getMimeType();
1436         if (contentMimeType != null) {
1437             int x = contentMimeType.indexOf(';');
1438             if (x > -1) {
1439                 contentMimeType = contentMimeType.substring(0, x);
1440             }
1441             contentMimeType = contentMimeType.trim();
1442         }
1443 
1444         f = createResult(FAILURE, "Content MIME types don't match!");
1445         addResult(results, assertEquals(docMimeType, contentMimeType, null, f));
1446 
1447         if (contentStream.getMimeType() != null) {
1448             if (contentMimeType.equals(docMimeType)) {
1449                 f = createResult(WARNING, "Content MIME types don't match!");
1450                 addResult(results, assertEquals(doc.getContentStreamMimeType(), contentStream.getMimeType(), null, f));
1451             }
1452 
1453             f = createResult(FAILURE, "Content MIME types is invalid: " + contentStream.getMimeType());
1454             addResult(
1455                     results,
1456                     assertIsTrue(contentStream.getMimeType().length() > 2
1457                             && contentStream.getMimeType().indexOf('/') > 0, null, f));
1458         }
1459 
1460         // check stream
1461         InputStream stream = contentStream.getStream();
1462         if (stream == null) {
1463             addResult(results, createResult(FAILURE, "Docuemnt has no content stream!"));
1464             return;
1465         }
1466 
1467         try {
1468             long bytes = 0;
1469             byte[] buffer = new byte[64 * 1024];
1470             int b = stream.read(buffer);
1471             while (b > -1) {
1472                 bytes += b;
1473                 b = stream.read(buffer);
1474             }
1475             stream.close();
1476 
1477             // check content length
1478             if (doc.getContentStreamLength() > -1) {
1479                 f = createResult(FAILURE,
1480                         "Content stream length property value doesn't match the actual content length!");
1481                 addResult(results, assertEquals(doc.getContentStreamLength(), bytes, null, f));
1482             }
1483 
1484             if (contentStream.getLength() > -1) {
1485                 f = createResult(FAILURE, "Content length value doesn't match the actual content length!");
1486                 addResult(results, assertEquals(contentStream.getLength(), bytes, null, f));
1487             }
1488         } catch (Exception e) {
1489             addResult(results, createResult(FAILURE, "Reading content failed: " + e, e, false));
1490         } finally {
1491             IOUtils.closeQuietly(stream);
1492         }
1493     }
1494 
1495     protected CmisTestResult checkRenditions(Session session, CmisObject object, String message) {
1496         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
1497 
1498         CmisTestResult f;
1499 
1500         if (object.getRenditions() != null) {
1501 
1502             for (Rendition rend : object.getRenditions()) {
1503                 f = createResult(FAILURE, "A rendition in the list of renditions is null!");
1504                 addResult(results, assertNotNull(rend, null, f));
1505 
1506                 if (rend != null) {
1507                     f = createResult(FAILURE, "A rendition has an empty stream id!");
1508                     addResult(results, assertStringNotEmpty(rend.getStreamId(), null, f));
1509 
1510                     f = createResult(FAILURE, "A rendition has an empty kind! Stream id: " + rend.getStreamId());
1511                     addResult(results, assertStringNotEmpty(rend.getKind(), null, f));
1512 
1513                     f = createResult(FAILURE, "A rendition has an empty MIME type! Stream id: " + rend.getStreamId());
1514                     addResult(results, assertStringNotEmpty(rend.getMimeType(), null, f));
1515 
1516                     if ("cmis:thumbnail".equals(rend.getKind())) {
1517                         f = createResult(WARNING,
1518                                 "A rendition is of kind 'cmis:thumbnail' but the height is not set or has an invalid value! Stream id: "
1519                                         + rend.getStreamId());
1520                         addResult(results, assertIsTrue(rend.getHeight() > 0, null, f));
1521 
1522                         f = createResult(WARNING,
1523                                 "A rendition is of kind 'cmis:thumbnail' but the width is not set or has an invalid value! Stream id: "
1524                                         + rend.getStreamId());
1525                         addResult(results, assertIsTrue(rend.getWidth() > 0, null, f));
1526                     }
1527 
1528                     // check the content
1529                     ContentStream contentStream = rend.getContentStream();
1530                     f = createResult(FAILURE, "A rendition has no content stream! Stream id: " + rend.getStreamId());
1531                     addResult(results, assertNotNull(contentStream, null, f));
1532 
1533                     if (contentStream != null) {
1534                         InputStream stream = contentStream.getStream();
1535 
1536                         f = createResult(FAILURE, "A rendition has no stream! Stream id: " + rend.getStreamId());
1537                         addResult(results, assertNotNull(stream, null, f));
1538 
1539                         if (stream != null) {
1540                             try {
1541                                 long bytes = 0;
1542                                 byte[] buffer = new byte[64 * 1024];
1543                                 int b = stream.read(buffer);
1544                                 while (b > -1) {
1545                                     bytes += b;
1546                                     b = stream.read(buffer);
1547                                 }
1548                                 stream.close();
1549 
1550                                 // check content length
1551                                 if (rend.getLength() > -1) {
1552                                     f = createResult(FAILURE,
1553                                             "Rendition content stream length value doesn't match the actual content length!");
1554                                     addResult(results, assertEquals(rend.getLength(), bytes, null, f));
1555                                 }
1556                             } catch (Exception e) {
1557                                 addResult(results, createResult(FAILURE, "Reading content failed: " + e, e, false));
1558                             } finally {
1559                                 IOUtils.closeQuietly(stream);
1560                             }
1561                         }
1562                     }
1563                 }
1564             }
1565         }
1566 
1567         CmisTestResultImpl result = createResult(getWorst(results), message);
1568         result.getChildren().addAll(results);
1569 
1570         return (result.getStatus().getLevel() <= OK.getLevel() ? null : result);
1571     }
1572 
1573     protected CmisTestResult checkVersionHistory(Session session, CmisObject object, String[] properties, String message) {
1574         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
1575 
1576         CmisTestResult f;
1577 
1578         if (object.getBaseTypeId() != BaseTypeId.CMIS_DOCUMENT) {
1579             // skip non-document objects
1580             return null;
1581         }
1582 
1583         if (!Boolean.TRUE.equals(((DocumentTypeDefinition) object.getType()).isVersionable())) {
1584             // skip non-versionable types
1585             return null;
1586         }
1587 
1588         Document doc = (Document) object;
1589 
1590         // check version series id
1591         String versionSeriesId = doc.getVersionSeriesId();
1592 
1593         f = createResult(FAILURE, "Versionable document has no version series id property!");
1594         addResult(results, assertStringNotEmpty(versionSeriesId, null, f));
1595         if (versionSeriesId == null) {
1596             CmisTestResultImpl result = createResult(getWorst(results), message);
1597             result.getChildren().addAll(results);
1598             return result;
1599         }
1600 
1601         // get version history
1602         List<Document> versions = doc.getAllVersions(SELECT_ALL_NO_CACHE_OC);
1603 
1604         f = createResult(FAILURE, "Version history is null!");
1605         addResult(results, assertNotNull(versions, null, f));
1606         if (versions == null) {
1607             CmisTestResultImpl result = createResult(getWorst(results), message);
1608             result.getChildren().addAll(results);
1609             return result;
1610         }
1611 
1612         f = createResult(FAILURE, "Version history must have at least one version!");
1613         addResult(results, assertListNotEmpty(versions, null, f));
1614 
1615         if (!versions.isEmpty()) {
1616             // get latest version
1617             Document lastestVersion = doc.getObjectOfLatestVersion(false, SELECT_ALL_NO_CACHE_OC);
1618             addResult(results,
1619                     checkObject(session, lastestVersion, properties, "Latest version check: " + lastestVersion.getId()));
1620 
1621             f = createResult(FAILURE, "Latest version is not flagged as latest version! Id: " + lastestVersion.getId());
1622             addResult(results, assertIsTrue(lastestVersion.isLatestVersion(), null, f));
1623 
1624             // get latest major version
1625             Document lastestMajorVersion = null;
1626             try {
1627                 lastestMajorVersion = doc.getObjectOfLatestVersion(true, SELECT_ALL_NO_CACHE_OC);
1628 
1629                 f = createResult(FAILURE, "getObjectOfLatestVersion returned an invalid object!");
1630                 addResult(results, assertNotNull(lastestMajorVersion, null, f));
1631             } catch (CmisObjectNotFoundException e) {
1632                 // no latest major version
1633             }
1634             if (lastestMajorVersion != null) {
1635                 addResult(
1636                         results,
1637                         checkObject(session, lastestMajorVersion, properties, "Latest major version check: "
1638                                 + lastestMajorVersion.getId()));
1639 
1640                 f = createResult(FAILURE, "Latest major version is not flagged as latest major version! Id: "
1641                         + lastestMajorVersion.getId());
1642                 addResult(results, assertIsTrue(lastestMajorVersion.isLatestMajorVersion(), null, f));
1643             }
1644 
1645             // iterate through the version history and test each version
1646             // document
1647             long creatationDate = Long.MAX_VALUE;
1648             int latestVersion = 0;
1649             int latestMajorVersion = 0;
1650             long latestModificationDate = Long.MAX_VALUE;
1651             int latestModifictaionIndex = Integer.MIN_VALUE;
1652             Set<String> versionLabels = new HashSet<String>();
1653             boolean found = false;
1654             boolean foundLastestVersion = false;
1655             boolean foundLastestMajorVersion = false;
1656             for (int i = 0; i < versions.size(); i++) {
1657                 Document version = versions.get(i);
1658 
1659                 f = createResult(FAILURE, "Version " + i + " is null!");
1660                 addResult(results, assertNotNull(version, null, f));
1661                 if (version == null) {
1662                     continue;
1663                 }
1664 
1665                 addResult(results, checkObject(session, version, properties, "Version check: " + version.getId()));
1666 
1667                 // check first entry
1668                 if (i == 0) {
1669                     if (version.isVersionSeriesCheckedOut()) {
1670                         f = createResult(
1671                                 WARNING,
1672                                 "Version series is checked-out and the PWC is not the latest version! Id: "
1673                                         + version.getId()
1674                                         + " (Note: The words of the CMIS specification define that the PWC is the latest version."
1675                                         + " But that is not the intention of the spec and will be changed in CMIS 1.1."
1676                                         + " Thus this a warning, not an error.)");
1677                         addResult(results, assertIsTrue(version.isLatestVersion(), null, f));
1678                     } else {
1679                         f = createResult(FAILURE,
1680                                 "Version series is not checked-out and first version history entry is not the latest version! Id: "
1681                                         + version.getId());
1682                         addResult(results, assertIsTrue(version.isLatestVersion(), null, f));
1683                     }
1684                 }
1685 
1686                 // check version id
1687                 f = createResult(FAILURE, "Version series id does not match! Id: " + version.getId());
1688                 addResult(results, assertEquals(versionSeriesId, version.getVersionSeriesId(), null, f));
1689 
1690                 // check creation date
1691                 if (creatationDate == version.getCreationDate().getTimeInMillis()) {
1692                     addResult(results, createResult(WARNING, "Two or more versions have the same creation date!"));
1693                 } else {
1694                     f = createResult(FAILURE, "Version history order incorrect! Must be sorted bei creation date!");
1695                     addResult(results,
1696                             assertIsTrue(version.getCreationDate().getTimeInMillis() <= creatationDate, null, f));
1697                 }
1698 
1699                 // count latest versions and latest major versions
1700                 if (version.isLatestVersion()) {
1701                     latestVersion++;
1702                 }
1703 
1704                 if (version.isLatestMajorVersion()) {
1705                     latestMajorVersion++;
1706                 }
1707 
1708                 // find latest modification date
1709                 if (latestModificationDate == version.getLastModificationDate().getTimeInMillis()) {
1710                     addResult(results,
1711                             createResult(WARNING, "Two or more versions have the same last modification date!"));
1712                 } else if (latestModificationDate < version.getLastModificationDate().getTimeInMillis()) {
1713                     latestModificationDate = version.getLastModificationDate().getTimeInMillis();
1714                     latestModifictaionIndex = i;
1715                 }
1716 
1717                 // check for version label duplicates
1718                 String versionLabel = version.getVersionLabel();
1719                 f = createResult(WARNING, "More than one version have this version label: " + versionLabel);
1720                 addResult(results, assertIsFalse(versionLabels.contains(versionLabel), null, f));
1721 
1722                 versionLabels.add(versionLabel);
1723 
1724                 // check PWC
1725                 if (version.getId().equals(version.getVersionSeriesCheckedOutId())) {
1726                     f = createResult(FAILURE, "PWC must not be flagged as latest major version! Id: " + version.getId());
1727                     addResult(results, assertIsFalse(version.isLatestMajorVersion(), null, f));
1728                 }
1729 
1730                 // check checked out
1731                 if (Boolean.TRUE.equals(doc.isVersionSeriesCheckedOut())) {
1732                     f = createResult(WARNING,
1733                             "Version series is marked as checked out but cmis:versionSeriesCheckedOutId is not set! Id: "
1734                                     + version.getId());
1735                     addResult(results, assertStringNotEmpty(doc.getVersionSeriesCheckedOutId(), null, f));
1736 
1737                     f = createResult(WARNING,
1738                             "Version series is marked as checked out but cmis:versionSeriesCheckedOutBy is not set! Id: "
1739                                     + version.getId());
1740                     addResult(results, assertStringNotEmpty(doc.getVersionSeriesCheckedOutBy(), null, f));
1741                 } else if (Boolean.FALSE.equals(doc.isVersionSeriesCheckedOut())) {
1742                     f = createResult(FAILURE,
1743                             "Version series is not marked as checked out but cmis:versionSeriesCheckedOutId is set! Id: "
1744                                     + version.getId());
1745                     addResult(results, assertNull(doc.getVersionSeriesCheckedOutId(), null, f));
1746 
1747                     f = createResult(FAILURE,
1748                             "Version series is not marked as checked out but cmis:versionSeriesCheckedOutIdBy is set! Id: "
1749                                     + version.getId());
1750                     addResult(results, assertNull(doc.getVersionSeriesCheckedOutBy(), null, f));
1751                 }
1752 
1753                 // found origin object?
1754                 if (version.getId().equals(object.getId())) {
1755                     found = true;
1756                 }
1757 
1758                 // found latest version?
1759                 if (version.getId().equals(lastestVersion.getId())) {
1760                     foundLastestVersion = true;
1761                 }
1762 
1763                 // found latest major version?
1764                 if (lastestMajorVersion != null && version.getId().equals(lastestMajorVersion.getId())) {
1765                     foundLastestMajorVersion = true;
1766                 }
1767             }
1768 
1769             // check latest versions
1770             f = createResult(FAILURE, "Version series id has " + latestVersion
1771                     + " latest versions! There must be only one!");
1772             addResult(results, assertEquals(1, latestVersion, null, f));
1773 
1774             if (!foundLastestVersion) {
1775                 addResult(results, createResult(FAILURE, "Latest version not found in version history!"));
1776             }
1777 
1778             // check latest major versions
1779             if (lastestMajorVersion == null) {
1780                 f = createResult(FAILURE, "Version series id has " + latestMajorVersion
1781                         + " latest major version(s) but getObjectOfLatestVersion() didn't return a major version!");
1782                 addResult(results, assertEquals(0, latestMajorVersion, null, f));
1783             } else {
1784                 f = createResult(FAILURE, "Version series id has " + latestMajorVersion
1785                         + " latest major versions but there should be exactly one!");
1786                 addResult(results, assertEquals(1, latestMajorVersion, null, f));
1787 
1788                 if (!foundLastestMajorVersion) {
1789                     addResult(results, createResult(FAILURE, "Latest major version not found in version history!"));
1790                 }
1791             }
1792 
1793             // check latest version
1794             if (latestModifictaionIndex >= 0) {
1795                 f = createResult(
1796                         FAILURE,
1797                         "Version with the latest modification date is not flagged as latest version! Id: "
1798                                 + versions.get(latestModifictaionIndex));
1799                 addResult(results, assertIsTrue(versions.get(latestModifictaionIndex).isLatestVersion(), null, f));
1800             }
1801 
1802             // check if the origin object was found
1803             if (!found) {
1804                 addResult(results, createResult(FAILURE, "Document not found in its version history!"));
1805             }
1806         }
1807 
1808         CmisTestResultImpl result = createResult(getWorst(results), message);
1809         result.getChildren().addAll(results);
1810 
1811         return (result.getStatus().getLevel() <= OK.getLevel() ? null : result);
1812     }
1813 
1814     protected CmisTestResult assertAllowableAction(CmisObject object, Action action, CmisTestResult success,
1815             CmisTestResult failure) {
1816         AllowableActions allowableActions = object.getAllowableActions();
1817         if (allowableActions != null && allowableActions.getAllowableActions() != null) {
1818             if (allowableActions.getAllowableActions().contains(action)) {
1819                 return success;
1820             }
1821         }
1822 
1823         return failure;
1824     }
1825 
1826     protected CmisTestResult assertNotAllowableAction(CmisObject object, Action action, CmisTestResult success,
1827             CmisTestResult failure) {
1828         AllowableActions allowableActions = object.getAllowableActions();
1829         if (allowableActions != null && allowableActions.getAllowableActions() != null) {
1830             if (!allowableActions.getAllowableActions().contains(action)) {
1831                 return success;
1832             }
1833         }
1834 
1835         return failure;
1836     }
1837 
1838     protected CmisTestResult checkProperty(Property<?> property, String message, PropertyCheckEnum propertyCheck) {
1839         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
1840 
1841         CmisTestResult f;
1842 
1843         f = createResult(FAILURE, "Property is not included in response!");
1844         addResult(results, assertNotNull(property, null, f));
1845 
1846         if (property != null) {
1847             f = createResult(FAILURE, "Property id is not set or empty!");
1848             addResult(results, assertStringNotEmpty(property.getId(), null, f));
1849 
1850             f = createResult(WARNING, "Display name is not set!");
1851             addResult(results, assertNotNull(property.getDisplayName(), null, f));
1852 
1853             f = createResult(WARNING, "Query name is not set!");
1854             addResult(results, assertNotNull(property.getQueryName(), null, f));
1855 
1856             f = createResult(WARNING, "Local name is not set!");
1857             addResult(results, assertNotNull(property.getLocalName(), null, f));
1858 
1859             if ((propertyCheck == PropertyCheckEnum.MUST_BE_SET)
1860                     || (propertyCheck == PropertyCheckEnum.STRING_MUST_NOT_BE_EMPTY)) {
1861                 f = createResult(FAILURE, "Property has no value!");
1862                 addResult(results, assertListNotEmpty(property.getValues(), null, f));
1863             } else if (propertyCheck == PropertyCheckEnum.STRING_SHOULD_NOT_BE_EMPTY) {
1864                 f = createResult(WARNING, "Property has no value!");
1865                 addResult(results, assertListNotEmpty(property.getValues(), null, f));
1866             } else if (propertyCheck == PropertyCheckEnum.MUST_NOT_BE_SET) {
1867                 f = createResult(FAILURE, "Property has a value!");
1868                 addResult(results, assertIsTrue(property.getValues().isEmpty(), null, f));
1869             }
1870 
1871             boolean isString = ((property.getDefinition().getPropertyType() == PropertyType.STRING)
1872                     || (property.getDefinition().getPropertyType() == PropertyType.ID)
1873                     || (property.getDefinition().getPropertyType() == PropertyType.URI) || (property.getDefinition()
1874                     .getPropertyType() == PropertyType.HTML));
1875             for (Object value : property.getValues()) {
1876                 if (value == null) {
1877                     addResult(results, createResult(FAILURE, "Property values contain a null value!"));
1878                     break;
1879                 } else if (isString) {
1880                     if (propertyCheck == PropertyCheckEnum.STRING_MUST_NOT_BE_EMPTY) {
1881                         f = createResult(FAILURE, "Property values contain an empty string!");
1882                         addResult(results, assertStringNotEmpty(value.toString(), null, f));
1883                     } else if (propertyCheck == PropertyCheckEnum.STRING_SHOULD_NOT_BE_EMPTY) {
1884                         f = createResult(WARNING, "Property values contain an empty string!");
1885                         addResult(results, assertStringNotEmpty(value.toString(), null, f));
1886                     }
1887                 }
1888             }
1889 
1890             if (property.getDefinition().getCardinality() == Cardinality.SINGLE) {
1891                 f = createResult(FAILURE, "Property cardinality is SINGLE but property has more than one value!");
1892                 addResult(results, assertIsTrue(property.getValues().size() <= 1, null, f));
1893             }
1894 
1895             if (property.getDefinition().isRequired() == null) {
1896                 addResult(results, createResult(FAILURE, "Property definition doesn't contain the required flag!"));
1897             } else {
1898                 if (property.getDefinition().isRequired().booleanValue()) {
1899                     f = createResult(FAILURE, "Property is required but has no value!");
1900                     addResult(results, assertListNotEmpty(property.getValues(), null, f));
1901                 }
1902             }
1903         }
1904 
1905         CmisTestResultImpl result = createResult(getWorst(results), message);
1906         result.getChildren().addAll(results);
1907 
1908         return (result.getStatus().getLevel() <= OK.getLevel() ? null : result);
1909     }
1910 
1911     protected CmisTestResult checkChildren(Session session, Folder folder, String message) {
1912         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
1913 
1914         CmisTestResult f;
1915 
1916         if (folder == null) {
1917             return createResult(FAILURE, "Folder is null!");
1918         }
1919 
1920         // getChildren
1921 
1922         boolean supportsOrderByName = isOrderByNameSupported(session);
1923         OperationContext orderContext = (supportsOrderByName ? SELECT_ALL_NO_CACHE_OC_ORDER_BY_NAME
1924                 : SELECT_ALL_NO_CACHE_OC);
1925 
1926         long childrenCount = 0;
1927         long childrenFolderCount = 0;
1928         ItemIterable<CmisObject> children = folder.getChildren(orderContext);
1929 
1930         int orderByNameIssues = 0;
1931         String lastName = null;
1932 
1933         for (CmisObject child : children) {
1934             childrenCount++;
1935             if (child instanceof Folder) {
1936                 childrenFolderCount++;
1937             }
1938 
1939             checkChild(session, results, folder, child);
1940 
1941             if (lastName != null && child.getName() != null) {
1942                 if (child.getName().compareToIgnoreCase(lastName) < 0) {
1943                     orderByNameIssues++;
1944                 }
1945             }
1946 
1947             lastName = child.getName();
1948         }
1949 
1950         if (children.getTotalNumItems() >= 0) {
1951             f = createResult(WARNING, "Number of children doesn't match the reported total number of items!");
1952             addResult(results, assertEquals(childrenCount, children.getTotalNumItems(), null, f));
1953         } else {
1954             addResult(results, createResult(WARNING, "getChildren did not report the total number of items!"));
1955         }
1956 
1957         if (supportsOrderByName) {
1958             f = createResult(WARNING,
1959                     "Children should be ordered by cmis:name, but they are not! (It might be a collation mismtach.)");
1960             addResult(results, assertEquals(0, orderByNameIssues, null, f));
1961         } else {
1962             addResult(results, createResult(INFO, "Repository doesn't support Order By for getChildren()."));
1963         }
1964 
1965         // test path segments
1966 
1967         ObjectInFolderList pathSegementChildren = session
1968                 .getBinding()
1969                 .getNavigationService()
1970                 .getChildren(session.getRepositoryInfo().getId(), folder.getId(), "cmis:objectId,cmis:name", null,
1971                         null, null, null, Boolean.TRUE, BigInteger.valueOf(10), BigInteger.ZERO, null);
1972 
1973         if (pathSegementChildren != null && pathSegementChildren.getObjects() != null) {
1974             for (ObjectInFolderData objectInFolder : pathSegementChildren.getObjects()) {
1975                 String pathSegement = objectInFolder.getPathSegment();
1976                 String objectId = (String) objectInFolder.getObject().getProperties().getProperties()
1977                         .get(PropertyIds.OBJECT_ID).getFirstValue();
1978 
1979                 if (pathSegement == null) {
1980                     addResult(results, createResult(FAILURE, "getChildren omitted path segement! Id: " + objectId));
1981                 } else {
1982                     CmisObject pathSegementChild = session.getObjectByPath(folder.getPath(), pathSegement);
1983 
1984                     f = createResult(FAILURE,
1985                             "Combining the path of the parent folder and the path segement of a child returns a different object! Id: "
1986                                     + objectId);
1987                     addResult(results, assertEquals(objectId, pathSegementChild.getId(), null, f));
1988                 }
1989             }
1990         }
1991 
1992         // getDescendants
1993 
1994         if (isGetDescendantsSupported(session)) {
1995             long descendantsCount = 0;
1996             List<Tree<FileableCmisObject>> descendants = folder.getDescendants(1, SELECT_ALL_NO_CACHE_OC);
1997 
1998             for (Tree<FileableCmisObject> child : descendants) {
1999                 descendantsCount++;
2000 
2001                 if (child == null) {
2002                     addResult(results, createResult(FAILURE, "Folder descendants contain a null tree!"));
2003                 } else {
2004                     checkChild(session, results, folder, child.getItem());
2005                 }
2006             }
2007 
2008             f = createResult(FAILURE,
2009                     "Number of descendants doesn't match the number of children returned by getChildren!");
2010             addResult(results, assertEquals(childrenCount, descendantsCount, null, f));
2011         } else {
2012             addResult(results, createResult(SKIPPED, "getDescendants is not supported."));
2013         }
2014 
2015         // getFolderTree
2016 
2017         if (isGetFolderTreeSupported(session)) {
2018             long folderTreeCount = 0;
2019             List<Tree<FileableCmisObject>> folderTree = folder.getFolderTree(1, SELECT_ALL_NO_CACHE_OC);
2020 
2021             for (Tree<FileableCmisObject> child : folderTree) {
2022                 folderTreeCount++;
2023 
2024                 if (child == null) {
2025                     addResult(results, createResult(FAILURE, "Folder tree contains a null tree!"));
2026                 } else {
2027                     checkChild(session, results, folder, child.getItem());
2028                 }
2029             }
2030 
2031             f = createResult(FAILURE, "Number of folders doesn't match the number of folders returned by getChildren!");
2032             addResult(results, assertEquals(childrenFolderCount, folderTreeCount, null, f));
2033         } else {
2034             addResult(results, createResult(SKIPPED, "getFolderTree is not supported."));
2035         }
2036 
2037         // --- wrap up ---
2038 
2039         CmisTestResultImpl result = createResult(getWorst(results), message);
2040         result.getChildren().addAll(results);
2041 
2042         return (result.getStatus().getLevel() <= OK.getLevel() ? null : result);
2043     }
2044 
2045     private void checkChild(Session session, List<CmisTestResult> results, Folder folder, CmisObject child) {
2046         CmisTestResult f;
2047 
2048         if (child == null) {
2049             addResult(results, createResult(FAILURE, "Folder contains a null child!"));
2050         } else {
2051             String[] propertiesToCheck = new String[child.getType().getPropertyDefinitions().size()];
2052 
2053             int i = 0;
2054             for (String propId : child.getType().getPropertyDefinitions().keySet()) {
2055                 propertiesToCheck[i++] = propId;
2056             }
2057 
2058             addResult(results, checkObject(session, child, propertiesToCheck, "Child check: " + child.getId()));
2059             addResult(
2060                     results,
2061                     checkVersionHistory(session, child, propertiesToCheck,
2062                             "Child version history check: " + child.getId()));
2063 
2064             f = createResult(FAILURE, "Child is not fileable! Id: " + child.getId() + " / Type: "
2065                     + child.getType().getId());
2066             addResult(results, assertIsTrue(child instanceof FileableCmisObject, null, f));
2067 
2068             if (child instanceof FileableCmisObject) {
2069                 FileableCmisObject fileableChild = (FileableCmisObject) child;
2070 
2071                 Set<Action> actions = fileableChild.getAllowableActions().getAllowableActions();
2072                 boolean hasObjectParentsAction = actions.contains(Action.CAN_GET_OBJECT_PARENTS);
2073                 boolean hasFolderParentAction = actions.contains(Action.CAN_GET_FOLDER_PARENT);
2074 
2075                 if (hasObjectParentsAction || hasFolderParentAction) {
2076                     List<Folder> parents = fileableChild.getParents();
2077 
2078                     f = createResult(FAILURE, "Child has no parents! Id: " + child.getId());
2079                     addResult(results, assertListNotEmpty(parents, null, f));
2080 
2081                     if (child instanceof Folder) {
2082                         f = createResult(FAILURE,
2083                                 "Child is a folder and has more than one parent! Id: " + child.getId());
2084                         addResult(results, assertIsFalse(parents.size() > 1, null, f));
2085 
2086                         Folder folderParent = ((Folder) child).getFolderParent();
2087                         if (folderParent == null) {
2088                             addResult(
2089                                     results,
2090                                     createResult(
2091                                             FAILURE,
2092                                             "getFolderParent() returns null for a non-root folder object! Id: "
2093                                                     + child.getId()));
2094                         } else {
2095                             f = createResult(FAILURE,
2096                                     "getFolderParent() returns wrong parent object! Id: " + child.getId());
2097                             addResult(results, assertEquals(folder.getId(), folderParent.getId(), null, f));
2098 
2099                             if (parents.size() > 0 && parents.get(0) != null) {
2100                                 f = createResult(FAILURE,
2101                                         "getFolderParent() and getParents() return different parents for a folder object! Id: "
2102                                                 + child.getId());
2103                                 addResult(results, assertEquals(parents.get(0).getId(), folderParent.getId(), null, f));
2104                             }
2105                         }
2106                     }
2107 
2108                     boolean foundParent = false;
2109                     for (Folder parent : parents) {
2110                         if (parent == null) {
2111                             f = createResult(FAILURE, "One of childs parents is null! Id: " + child.getId());
2112                             addResult(results, assertListNotEmpty(parents, null, f));
2113                         } else if (folder.getId().equals(parent.getId())) {
2114                             foundParent = true;
2115                             break;
2116                         }
2117                     }
2118 
2119                     if (!foundParent) {
2120                         addResult(
2121                                 results,
2122                                 createResult(FAILURE,
2123                                         "Parent folder is not in parents of the child! Id: " + child.getId()));
2124                     }
2125                 }
2126 
2127                 // get object by id and compare
2128                 CmisObject objectById = session.getObject(child.getId(), SELECT_ALL_NO_CACHE_OC);
2129 
2130                 f = createResult(FAILURE, "Child and object fetched by id don't match! Id: " + child.getId());
2131                 addResult(results, assertEquals(child, objectById, null, f, false, false));
2132 
2133                 // get object by path and compare
2134                 List<String> paths = ((FileableCmisObject) child).getPaths();
2135 
2136                 if (isNullOrEmpty(paths)) {
2137                     addResult(results, createResult(FAILURE, "Child has no path! " + child.getId()));
2138                 } else {
2139                     for (String path : paths) {
2140                         CmisObject objectByPath = session.getObjectByPath(path, SELECT_ALL_NO_CACHE_OC);
2141 
2142                         f = createResult(FAILURE, "Child and object fetched by path don't match! Id: " + child.getId()
2143                                 + " / Path: " + path);
2144                         addResult(results, assertEquals(child, objectByPath, null, f, false, false));
2145 
2146                         f = createResult(FAILURE, "Object fetched by id and object fetched by path don't match! Id: "
2147                                 + child.getId() + " / Path: " + path);
2148                         addResult(results, assertEquals(objectById, objectByPath, null, f, true, true));
2149                     }
2150                 }
2151             }
2152 
2153             f = createResult(WARNING, "Child has no CAN_GET_OBJECT_PARENTS allowable action! Id: " + child.getId());
2154             addResult(results, assertAllowableAction(child, Action.CAN_GET_OBJECT_PARENTS, null, f));
2155 
2156             if (child instanceof Folder) {
2157                 f = createResult(WARNING, "Child has no CAN_GET_FOLDER_PARENT allowable action! Id: " + child.getId());
2158                 addResult(results, assertAllowableAction(child, Action.CAN_GET_FOLDER_PARENT, null, f));
2159             }
2160         }
2161     }
2162 
2163     protected CmisTestResult assertShallowEquals(CmisObject expected, CmisObject actual, CmisTestResult success,
2164             CmisTestResult failure) {
2165 
2166         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
2167 
2168         CmisTestResult f;
2169 
2170         if ((expected == null) && (actual == null)) {
2171             return success;
2172         }
2173 
2174         if (expected == null) {
2175             f = createResult(FAILURE, "Expected object is null, but actual object is not!");
2176             addResultChild(failure, f);
2177 
2178             return failure;
2179         }
2180 
2181         if (actual == null) {
2182             f = createResult(FAILURE, "Actual object is null, but expected object is not!");
2183             addResultChild(failure, f);
2184 
2185             return failure;
2186         }
2187 
2188         f = createResult(FAILURE, "Ids don't match!");
2189         addResult(results, assertEquals(expected.getId(), actual.getId(), null, f));
2190 
2191         f = createResult(FAILURE, "Base types don't match!");
2192         addResult(results, assertEquals(expected.getBaseTypeId(), actual.getBaseTypeId(), null, f));
2193 
2194         f = createResult(FAILURE, "Types don't match!");
2195         addResult(results, assertEquals(expected.getType().getId(), actual.getType().getId(), null, f));
2196 
2197         if (getWorst(results).getLevel() <= OK.getLevel()) {
2198             for (CmisTestResult result : results) {
2199                 addResultChild(success, result);
2200             }
2201 
2202             return success;
2203         } else {
2204             for (CmisTestResult result : results) {
2205                 addResultChild(failure, result);
2206             }
2207 
2208             return failure;
2209         }
2210     }
2211 
2212     // --- type checks ---
2213 
2214     protected CmisTestResult checkQueryName(String queryName, boolean isRequired, String message) {
2215         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
2216 
2217         CmisTestResult f;
2218 
2219         if (queryName == null || queryName.length() == 0) {
2220             addResult(results, createResult(isRequired ? FAILURE : WARNING, "Query name is not set!"));
2221         } else {
2222             f = createResult(FAILURE, "Query name contains invalid character: ' '");
2223             addResult(results, assertIsTrue(queryName.indexOf(' ') < 0, null, f));
2224 
2225             f = createResult(FAILURE, "Query name contains invalid character: ','");
2226             addResult(results, assertIsTrue(queryName.indexOf(',') < 0, null, f));
2227 
2228             f = createResult(FAILURE, "Query name contains invalid character: '\"'");
2229             addResult(results, assertIsTrue(queryName.indexOf('"') < 0, null, f));
2230 
2231             f = createResult(FAILURE, "Query name contains invalid character: '''");
2232             addResult(results, assertIsTrue(queryName.indexOf('\'') < 0, null, f));
2233 
2234             f = createResult(FAILURE, "Query name contains invalid character: '\\'");
2235             addResult(results, assertIsTrue(queryName.indexOf('\\') < 0, null, f));
2236 
2237             f = createResult(FAILURE, "Query name contains invalid character: '.'");
2238             addResult(results, assertIsTrue(queryName.indexOf('.') < 0, null, f));
2239 
2240             f = createResult(FAILURE, "Query name contains invalid character: '('");
2241             addResult(results, assertIsTrue(queryName.indexOf('(') < 0, null, f));
2242 
2243             f = createResult(FAILURE, "Query name contains invalid character: ')'");
2244             addResult(results, assertIsTrue(queryName.indexOf(')') < 0, null, f));
2245 
2246             f = createResult(FAILURE, "Query name contains invalid character: '\\t'");
2247             addResult(results, assertIsTrue(queryName.indexOf('\t') < 0, null, f));
2248 
2249             f = createResult(FAILURE, "Query name contains invalid character: '\\n'");
2250             addResult(results, assertIsTrue(queryName.indexOf('\n') < 0, null, f));
2251 
2252             f = createResult(FAILURE, "Query name contains invalid character: '\\r'");
2253             addResult(results, assertIsTrue(queryName.indexOf('\r') < 0, null, f));
2254         }
2255 
2256         CmisTestResultImpl result = createResult(getWorst(results), message);
2257         result.getChildren().addAll(results);
2258 
2259         return (result.getStatus().getLevel() <= OK.getLevel() ? null : result);
2260     }
2261 
2262     protected CmisTestResult checkTypeDefinition(Session session, TypeDefinition type, String message) {
2263         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
2264 
2265         CmisTestResult f;
2266 
2267         f = createResult(FAILURE, "Type is null!");
2268         addResult(results, assertNotNull(type, null, f));
2269 
2270         if (type != null) {
2271             f = createResult(FAILURE, "Type id is not set!");
2272             addResult(results, assertStringNotEmpty(type.getId(), null, f));
2273 
2274             f = createResult(FAILURE, "Base type id is not set!");
2275             addResult(results, assertNotNull(type.getBaseTypeId(), null, f));
2276 
2277             f = createResult(FAILURE, "Local name is not set!");
2278             addResult(results, assertStringNotEmpty(type.getLocalName(), null, f));
2279 
2280             // f = createResult(FAILURE, "Local namespace is not set!");
2281             // addResult(results, assertStringNotEmpty(type.(), null, f));
2282 
2283             boolean isQueryNameRequired = Boolean.TRUE.equals(type.isQueryable());
2284             addResult(results,
2285                     checkQueryName(type.getQueryName(), isQueryNameRequired, "Type Query Name: " + type.getQueryName()));
2286 
2287             if ((type.getId() != null) && (type.getBaseTypeId() != null)) {
2288                 if (type.getBaseTypeId().value().equals(type.getId())) {
2289                     f = createResult(FAILURE, "Base type has parent type!");
2290                     addResult(results, assertStringNullOrEmpty(type.getParentTypeId(), null, f));
2291                 } else {
2292                     f = createResult(FAILURE, "Parent type is not set!");
2293                     addResult(results, assertStringNotEmpty(type.getParentTypeId(), null, f));
2294                 }
2295             }
2296 
2297             f = createResult(FAILURE, "Creatable flag is not set!");
2298             addResult(results, assertNotNull(type.isCreatable(), null, f));
2299 
2300             f = createResult(FAILURE, "Fileable flag is not set!");
2301             addResult(results, assertNotNull(type.isFileable(), null, f));
2302 
2303             f = createResult(FAILURE, "Controllable ACL flag is not set!");
2304             addResult(results, assertNotNull(type.isControllableAcl(), null, f));
2305 
2306             f = createResult(FAILURE, "Controllable Policy flag is not set!");
2307             addResult(results, assertNotNull(type.isControllablePolicy(), null, f));
2308 
2309             f = createResult(FAILURE, "Fulltext indexed flag is not set!");
2310             addResult(results, assertNotNull(type.isFulltextIndexed(), null, f));
2311 
2312             f = createResult(FAILURE, "Included in super type flag is not set!");
2313             addResult(results, assertNotNull(type.isIncludedInSupertypeQuery(), null, f));
2314 
2315             f = createResult(FAILURE, "Queryable flag is not set!");
2316             addResult(results, assertNotNull(type.isQueryable(), null, f));
2317 
2318             f = createResult(WARNING, "Type display name is not set!");
2319             addResult(results, assertStringNotEmpty(type.getDisplayName(), null, f));
2320 
2321             f = createResult(WARNING, "Type description is not set!");
2322             addResult(results, assertStringNotEmpty(type.getDescription(), null, f));
2323 
2324             if (BaseTypeId.CMIS_DOCUMENT.equals(type.getBaseTypeId())) {
2325                 DocumentTypeDefinition docType = (DocumentTypeDefinition) type;
2326 
2327                 f = createResult(FAILURE, "Versionable flag is not set!");
2328                 addResult(results, assertNotNull(docType.isVersionable(), null, f));
2329 
2330                 f = createResult(FAILURE, "Content stream allowed flag is not set!");
2331                 addResult(results, assertNotNull(docType.getContentStreamAllowed(), null, f));
2332             } else if (BaseTypeId.CMIS_FOLDER.equals(type.getBaseTypeId())) {
2333                 if (type.isFileable() != null) {
2334                     f = createResult(FAILURE, "Folder types must be fileable!");
2335                     addResult(results, assertIsTrue(type.isFileable(), null, f));
2336                 }
2337             } else if (BaseTypeId.CMIS_RELATIONSHIP.equals(type.getBaseTypeId())) {
2338                 RelationshipTypeDefinition relType = (RelationshipTypeDefinition) type;
2339 
2340                 f = createResult(FAILURE, "Allowed Source Type Ids are not set!");
2341                 addResult(results, assertNotNull(relType.getAllowedSourceTypeIds(), null, f));
2342 
2343                 if (relType.getAllowedSourceTypeIds() != null) {
2344                     for (String typeId : relType.getAllowedSourceTypeIds()) {
2345                         try {
2346                             session.getTypeDefinition(typeId);
2347                         } catch (CmisInvalidArgumentException e) {
2348                             addResult(
2349                                     results,
2350                                     createResult(WARNING,
2351                                             "Allowed Source Type Ids contain a type id that doesn't exist: " + typeId));
2352                         } catch (CmisObjectNotFoundException e) {
2353                             addResult(
2354                                     results,
2355                                     createResult(WARNING,
2356                                             "Allowed Source Type Ids contain a type id that doesn't exist: " + typeId));
2357                         }
2358                     }
2359                 }
2360 
2361                 f = createResult(FAILURE, "Allowed Target Type Ids are not set!");
2362                 addResult(results, assertNotNull(relType.getAllowedTargetTypeIds(), null, f));
2363 
2364                 if (relType.getAllowedTargetTypeIds() != null) {
2365                     for (String typeId : relType.getAllowedTargetTypeIds()) {
2366                         try {
2367                             session.getTypeDefinition(typeId);
2368                         } catch (CmisInvalidArgumentException e) {
2369                             addResult(
2370                                     results,
2371                                     createResult(WARNING,
2372                                             "Allowed Target Type Ids contain a type id that doesn't exist: " + typeId));
2373                         } catch (CmisObjectNotFoundException e) {
2374                             addResult(
2375                                     results,
2376                                     createResult(WARNING,
2377                                             "Allowed Target Type Ids contain a type id that doesn't exist: " + typeId));
2378                         }
2379                     }
2380                 }
2381 
2382                 if (type.isFileable() != null) {
2383                     f = createResult(FAILURE, "Relationship types must not be fileable!");
2384                     addResult(results, assertIsFalse(type.isFileable(), null, f));
2385                 }
2386             } else if (BaseTypeId.CMIS_POLICY.equals(type.getBaseTypeId())) {
2387                 // nothing to do
2388             }
2389 
2390             // check properties
2391             if (!BaseTypeId.CMIS_SECONDARY.equals(type.getBaseTypeId())) {
2392 
2393                 f = createResult(FAILURE, "Type has no property definitions!");
2394                 addResult(results, assertNotNull(type.getPropertyDefinitions(), null, f));
2395 
2396                 if (type.getPropertyDefinitions() != null) {
2397                     for (PropertyDefinition<?> propDef : type.getPropertyDefinitions().values()) {
2398                         if (propDef == null) {
2399                             addResult(results, createResult(FAILURE, "A property definition is null!"));
2400                         } else if (propDef.getId() == null) {
2401                             addResult(results, createResult(FAILURE, "A property definition id is null!"));
2402                         } else {
2403                             addResult(results,
2404                                     checkPropertyDefinition(propDef, "Property definition: " + propDef.getId()));
2405                         }
2406                     }
2407                 }
2408 
2409                 CmisPropertyDefintion cpd;
2410 
2411                 // cmis:name
2412                 cpd = new CmisPropertyDefintion(PropertyIds.NAME, null, PropertyType.STRING, Cardinality.SINGLE, null,
2413                         null, null);
2414                 addResult(results, cpd.check(type));
2415 
2416                 // cmis:objectId
2417                 cpd = new CmisPropertyDefintion(PropertyIds.OBJECT_ID, false, PropertyType.ID, Cardinality.SINGLE,
2418                         Updatability.READONLY, null, null);
2419                 addResult(results, cpd.check(type));
2420 
2421                 // cmis:baseTypeId
2422                 cpd = new CmisPropertyDefintion(PropertyIds.BASE_TYPE_ID, false, PropertyType.ID, Cardinality.SINGLE,
2423                         Updatability.READONLY, null, null);
2424                 addResult(results, cpd.check(type));
2425 
2426                 // cmis:objectTypeId
2427                 cpd = new CmisPropertyDefintion(PropertyIds.OBJECT_TYPE_ID, true, PropertyType.ID, Cardinality.SINGLE,
2428                         Updatability.ONCREATE, null, null);
2429                 addResult(results, cpd.check(type));
2430 
2431                 // cmis:createdBy
2432                 cpd = new CmisPropertyDefintion(PropertyIds.CREATED_BY, false, PropertyType.STRING, Cardinality.SINGLE,
2433                         Updatability.READONLY, true, true);
2434                 addResult(results, cpd.check(type));
2435 
2436                 // cmis:creationDate
2437                 cpd = new CmisPropertyDefintion(PropertyIds.CREATION_DATE, false, PropertyType.DATETIME,
2438                         Cardinality.SINGLE, Updatability.READONLY, true, true);
2439                 addResult(results, cpd.check(type));
2440 
2441                 // cmis:lastModifiedBy
2442                 cpd = new CmisPropertyDefintion(PropertyIds.LAST_MODIFIED_BY, false, PropertyType.STRING,
2443                         Cardinality.SINGLE, Updatability.READONLY, true, true);
2444                 addResult(results, cpd.check(type));
2445 
2446                 // cmis:lastModificationDate
2447                 cpd = new CmisPropertyDefintion(PropertyIds.LAST_MODIFICATION_DATE, false, PropertyType.DATETIME,
2448                         Cardinality.SINGLE, Updatability.READONLY, true, true);
2449                 addResult(results, cpd.check(type));
2450 
2451                 // cmis:changeToken
2452                 cpd = new CmisPropertyDefintion(PropertyIds.CHANGE_TOKEN, false, PropertyType.STRING,
2453                         Cardinality.SINGLE, Updatability.READONLY, null, null);
2454                 addResult(results, cpd.check(type));
2455 
2456                 // CMIS 1.1 properties
2457                 if (session.getRepositoryInfo().getCmisVersion() == CmisVersion.CMIS_1_1) {
2458                     // cmis:description
2459                     cpd = new CmisPropertyDefintion(PropertyIds.DESCRIPTION, null, PropertyType.STRING,
2460                             Cardinality.SINGLE, null, null, null);
2461                     addResult(results, cpd.check(type));
2462 
2463                     // cmis:secondaryObjectTypeIds
2464                     cpd = new CmisPropertyDefintion(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, false, PropertyType.ID,
2465                             Cardinality.MULTI, null, null, false);
2466                     addResult(results, cpd.check(type));
2467 
2468                     if (BaseTypeId.CMIS_DOCUMENT.equals(type.getBaseTypeId())) {
2469                         // cmis:isPrivateWorkingCopy
2470                         cpd = new CmisPropertyDefintion(PropertyIds.IS_PRIVATE_WORKING_COPY, null,
2471                                 PropertyType.BOOLEAN, Cardinality.SINGLE, Updatability.READONLY, null, null);
2472                         addResult(results, cpd.check(type));
2473                     }
2474                 }
2475 
2476                 if (BaseTypeId.CMIS_DOCUMENT.equals(type.getBaseTypeId())) {
2477                     // cmis:isImmutable
2478                     cpd = new CmisPropertyDefintion(PropertyIds.IS_IMMUTABLE, false, PropertyType.BOOLEAN,
2479                             Cardinality.SINGLE, Updatability.READONLY, null, null);
2480                     addResult(results, cpd.check(type));
2481 
2482                     // cmis:isLatestVersion
2483                     cpd = new CmisPropertyDefintion(PropertyIds.IS_LATEST_VERSION, false, PropertyType.BOOLEAN,
2484                             Cardinality.SINGLE, Updatability.READONLY, null, null);
2485                     addResult(results, cpd.check(type));
2486 
2487                     // cmis:isMajorVersion
2488                     cpd = new CmisPropertyDefintion(PropertyIds.IS_MAJOR_VERSION, false, PropertyType.BOOLEAN,
2489                             Cardinality.SINGLE, Updatability.READONLY, null, null);
2490                     addResult(results, cpd.check(type));
2491 
2492                     // cmis:isLatestMajorVersion
2493                     cpd = new CmisPropertyDefintion(PropertyIds.IS_LATEST_MAJOR_VERSION, false, PropertyType.BOOLEAN,
2494                             Cardinality.SINGLE, Updatability.READONLY, null, null);
2495                     addResult(results, cpd.check(type));
2496 
2497                     // cmis:versionLabel
2498                     cpd = new CmisPropertyDefintion(PropertyIds.VERSION_LABEL, false, PropertyType.STRING,
2499                             Cardinality.SINGLE, Updatability.READONLY, null, null);
2500                     addResult(results, cpd.check(type));
2501 
2502                     // cmis:versionSeriesId
2503                     cpd = new CmisPropertyDefintion(PropertyIds.VERSION_SERIES_ID, false, PropertyType.ID,
2504                             Cardinality.SINGLE, Updatability.READONLY, null, null);
2505                     addResult(results, cpd.check(type));
2506 
2507                     // cmis:isVersionSeriesCheckedOut
2508                     cpd = new CmisPropertyDefintion(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT, false,
2509                             PropertyType.BOOLEAN, Cardinality.SINGLE, Updatability.READONLY, null, null);
2510                     addResult(results, cpd.check(type));
2511 
2512                     // cmis:versionSeriesCheckedOutBy
2513                     cpd = new CmisPropertyDefintion(PropertyIds.VERSION_SERIES_CHECKED_OUT_BY, false,
2514                             PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, null, null);
2515                     addResult(results, cpd.check(type));
2516 
2517                     // cmis:versionSeriesCheckedOutId
2518                     cpd = new CmisPropertyDefintion(PropertyIds.VERSION_SERIES_CHECKED_OUT_ID, false, PropertyType.ID,
2519                             Cardinality.SINGLE, Updatability.READONLY, null, null);
2520                     addResult(results, cpd.check(type));
2521 
2522                     // cmis:checkinComment
2523                     cpd = new CmisPropertyDefintion(PropertyIds.CHECKIN_COMMENT, false, PropertyType.STRING,
2524                             Cardinality.SINGLE, Updatability.READONLY, null, null);
2525                     addResult(results, cpd.check(type));
2526 
2527                     // cmis:contentStreamLength
2528                     cpd = new CmisPropertyDefintion(PropertyIds.CONTENT_STREAM_LENGTH, false, PropertyType.INTEGER,
2529                             Cardinality.SINGLE, Updatability.READONLY, null, null);
2530                     addResult(results, cpd.check(type));
2531 
2532                     // cmis:contentStreamMimeType
2533                     cpd = new CmisPropertyDefintion(PropertyIds.CONTENT_STREAM_MIME_TYPE, false, PropertyType.STRING,
2534                             Cardinality.SINGLE, Updatability.READONLY, null, null);
2535                     addResult(results, cpd.check(type));
2536 
2537                     // cmis:contentStreamFileName
2538                     cpd = new CmisPropertyDefintion(PropertyIds.CONTENT_STREAM_FILE_NAME, false, PropertyType.STRING,
2539                             Cardinality.SINGLE, Updatability.READONLY, null, null);
2540                     addResult(results, cpd.check(type));
2541 
2542                     // cmis:contentStreamId
2543                     cpd = new CmisPropertyDefintion(PropertyIds.CONTENT_STREAM_ID, false, PropertyType.ID,
2544                             Cardinality.SINGLE, Updatability.READONLY, null, null);
2545                     addResult(results, cpd.check(type));
2546                 } else if (BaseTypeId.CMIS_FOLDER.equals(type.getBaseTypeId())) {
2547                     // cmis:parentId
2548                     cpd = new CmisPropertyDefintion(PropertyIds.PARENT_ID, false, PropertyType.ID, Cardinality.SINGLE,
2549                             Updatability.READONLY, null, null);
2550                     addResult(results, cpd.check(type));
2551 
2552                     // cmis:path
2553                     cpd = new CmisPropertyDefintion(PropertyIds.PATH, false, PropertyType.STRING, Cardinality.SINGLE,
2554                             Updatability.READONLY, null, null);
2555                     addResult(results, cpd.check(type));
2556 
2557                     // cmis:allowedChildObjectTypeIds
2558                     cpd = new CmisPropertyDefintion(PropertyIds.ALLOWED_CHILD_OBJECT_TYPE_IDS, false, PropertyType.ID,
2559                             Cardinality.MULTI, Updatability.READONLY, null, false);
2560                     addResult(results, cpd.check(type));
2561                 } else if (BaseTypeId.CMIS_RELATIONSHIP.equals(type.getBaseTypeId())) {
2562                     // cmis:sourceId
2563                     cpd = new CmisPropertyDefintion(PropertyIds.SOURCE_ID, true, PropertyType.ID, Cardinality.SINGLE,
2564                             null, null, null);
2565                     addResult(results, cpd.check(type));
2566 
2567                     // cmis:targetId
2568                     cpd = new CmisPropertyDefintion(PropertyIds.TARGET_ID, true, PropertyType.ID, Cardinality.SINGLE,
2569                             null, null, null);
2570                     addResult(results, cpd.check(type));
2571                 } else if (BaseTypeId.CMIS_POLICY.equals(type.getBaseTypeId())) {
2572                     // cmis:policyText
2573                     cpd = new CmisPropertyDefintion(PropertyIds.POLICY_TEXT, null, PropertyType.STRING,
2574                             Cardinality.SINGLE, null, null, null);
2575                     addResult(results, cpd.check(type));
2576                 }
2577             }
2578         }
2579 
2580         CmisTestResultImpl result = createResult(getWorst(results), message);
2581         result.getChildren().addAll(results);
2582 
2583         return (result.getStatus().getLevel() <= OK.getLevel() ? null : result);
2584     }
2585 
2586     protected CmisTestResult checkPropertyDefinition(PropertyDefinition<?> propDef, String message) {
2587         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
2588 
2589         CmisTestResult f;
2590 
2591         f = createResult(FAILURE, "Property definition is null!");
2592         addResult(results, assertNotNull(propDef, null, f));
2593 
2594         if (propDef != null) {
2595             f = createResult(FAILURE, "Property id is not set!");
2596             addResult(results, assertStringNotEmpty(propDef.getId(), null, f));
2597 
2598             f = createResult(WARNING, "Local name is not set!");
2599             addResult(results, assertStringNotEmpty(propDef.getLocalName(), null, f));
2600 
2601             // f = createResult(WARNING, "Local namespace is not set!");
2602             // addResult(results,
2603             // assertStringNotEmpty(propDef.getLocalNamespace(), null, f));
2604 
2605             f = createResult(FAILURE, "Query name is not set!");
2606             addResult(results, assertStringNotEmpty(propDef.getQueryName(), null, f));
2607 
2608             f = createResult(WARNING, "Display name is not set!");
2609             addResult(results, assertStringNotEmpty(propDef.getDisplayName(), null, f));
2610 
2611             f = createResult(WARNING, "Description is not set!");
2612             addResult(results, assertStringNotEmpty(propDef.getDescription(), null, f));
2613 
2614             f = createResult(FAILURE, "Property type is not set!");
2615             addResult(results, assertNotNull(propDef.getPropertyType(), null, f));
2616 
2617             f = createResult(FAILURE, "Cardinality is not set!");
2618             addResult(results, assertNotNull(propDef.getCardinality(), null, f));
2619 
2620             f = createResult(FAILURE, "Updatability is not set!");
2621             addResult(results, assertNotNull(propDef.getUpdatability(), null, f));
2622 
2623             f = createResult(FAILURE, "Inherited flag is not set!");
2624             addResult(results, assertNotNull(propDef.isInherited(), null, f));
2625 
2626             f = createResult(FAILURE, "Required flag is not set!");
2627             addResult(results, assertNotNull(propDef.isRequired(), null, f));
2628 
2629             f = createResult(FAILURE, "Queryable flag is not set!");
2630             addResult(results, assertNotNull(propDef.isQueryable(), null, f));
2631 
2632             f = createResult(FAILURE, "Orderable flag is not set!");
2633             addResult(results, assertNotNull(propDef.isOrderable(), null, f));
2634         }
2635 
2636         CmisTestResultImpl result = createResult(getWorst(results), message);
2637         result.getChildren().addAll(results);
2638 
2639         return (result.getStatus().getLevel() <= OK.getLevel() ? null : result);
2640     }
2641 
2642     protected CmisTestResult assertEquals(TypeDefinition expected, TypeDefinition actual, CmisTestResult success,
2643             CmisTestResult failure) {
2644 
2645         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
2646 
2647         CmisTestResult f;
2648 
2649         if ((expected == null) && (actual == null)) {
2650             return success;
2651         }
2652 
2653         if (expected == null) {
2654             f = createResult(FAILURE, "Expected type defintion is null, but actual type defintion is not!");
2655             addResultChild(failure, f);
2656 
2657             return failure;
2658         }
2659 
2660         if (actual == null) {
2661             f = createResult(FAILURE, "Actual type defintion is null, but expected type defintion is not!");
2662             addResultChild(failure, f);
2663 
2664             return failure;
2665         }
2666 
2667         f = createResult(FAILURE, "Type ids don't match!");
2668         addResult(results, assertEquals(expected.getId(), actual.getId(), null, f));
2669 
2670         f = createResult(FAILURE, "Base type ids don't match!");
2671         addResult(results, assertEquals(expected.getBaseTypeId(), actual.getBaseTypeId(), null, f));
2672 
2673         f = createResult(FAILURE, "Parent type ids don't match!");
2674         addResult(results, assertEquals(expected.getParentTypeId(), actual.getParentTypeId(), null, f));
2675 
2676         f = createResult(FAILURE, "Query names don't match!");
2677         addResult(results, assertEquals(expected.getQueryName(), actual.getQueryName(), null, f));
2678 
2679         f = createResult(FAILURE, "Local names don't match!");
2680         addResult(results, assertEquals(expected.getLocalName(), actual.getLocalName(), null, f));
2681 
2682         f = createResult(FAILURE, "Local namespaces don't match!");
2683         addResult(results, assertEquals(expected.getLocalNamespace(), actual.getLocalNamespace(), null, f));
2684 
2685         f = createResult(FAILURE, "Display names don't match!");
2686         addResult(results, assertEquals(expected.getDisplayName(), actual.getDisplayName(), null, f));
2687 
2688         f = createResult(FAILURE, "Descriptions don't match!");
2689         addResult(results, assertEquals(expected.getDescription(), actual.getDescription(), null, f));
2690 
2691         f = createResult(FAILURE, "Controllable ACl flags don't match!");
2692         addResult(results, assertEquals(expected.isControllableAcl(), actual.isControllableAcl(), null, f));
2693 
2694         f = createResult(FAILURE, "Controllable Policy flags don't match!");
2695         addResult(results, assertEquals(expected.isControllablePolicy(), actual.isControllablePolicy(), null, f));
2696 
2697         f = createResult(FAILURE, "Creatable flags don't match!");
2698         addResult(results, assertEquals(expected.isCreatable(), actual.isCreatable(), null, f));
2699 
2700         f = createResult(FAILURE, "Fileable flags don't match!");
2701         addResult(results, assertEquals(expected.isFileable(), actual.isFileable(), null, f));
2702 
2703         f = createResult(FAILURE, "Fulltext indexed flags don't match!");
2704         addResult(results, assertEquals(expected.isFulltextIndexed(), actual.isFulltextIndexed(), null, f));
2705 
2706         f = createResult(FAILURE, "Queryable flags don't match!");
2707         addResult(results, assertEquals(expected.isQueryable(), actual.isQueryable(), null, f));
2708 
2709         f = createResult(FAILURE, "Included in supertype query flags don't match!");
2710         addResult(results,
2711                 assertEquals(expected.isIncludedInSupertypeQuery(), actual.isIncludedInSupertypeQuery(), null, f));
2712 
2713         if (expected.getTypeMutability() != null && actual.getTypeMutability() != null) {
2714             f = createResult(FAILURE, "Type Mutability: Create flags don't match!");
2715             addResult(
2716                     results,
2717                     assertEquals(expected.getTypeMutability().canCreate(), actual.getTypeMutability().canCreate(),
2718                             null, f));
2719 
2720             f = createResult(FAILURE, "Type Mutability: update flags don't match!");
2721             addResult(
2722                     results,
2723                     assertEquals(expected.getTypeMutability().canUpdate(), actual.getTypeMutability().canUpdate(),
2724                             null, f));
2725 
2726             f = createResult(FAILURE, "Type Mutability: delete flags don't match!");
2727             addResult(
2728                     results,
2729                     assertEquals(expected.getTypeMutability().canDelete(), actual.getTypeMutability().canDelete(),
2730                             null, f));
2731         } else {
2732             f = createResult(FAILURE, "Type Mutability infos don't match!");
2733             addResult(results, assertEquals(expected.getTypeMutability(), actual.getTypeMutability(), null, f));
2734         }
2735 
2736         if ((expected.getPropertyDefinitions() != null) && (actual.getPropertyDefinitions() != null)) {
2737             Map<String, PropertyDefinition<?>> epd = expected.getPropertyDefinitions();
2738             Map<String, PropertyDefinition<?>> apd = actual.getPropertyDefinitions();
2739 
2740             f = createResult(FAILURE, "Different number of property defintions!");
2741             addResult(results, assertEquals(epd.size(), apd.size(), null, f));
2742 
2743             for (PropertyDefinition<?> pd : epd.values()) {
2744                 f = createResult(FAILURE, "Property definition mismatch: " + pd.getId());
2745                 addResult(results, assertEquals(pd, apd.get(pd.getId()), null, f));
2746             }
2747         }
2748 
2749         if (getWorst(results).getLevel() <= OK.getLevel()) {
2750             for (CmisTestResult result : results) {
2751                 addResultChild(success, result);
2752             }
2753 
2754             return success;
2755         } else {
2756             for (CmisTestResult result : results) {
2757                 addResultChild(failure, result);
2758             }
2759 
2760             return failure;
2761         }
2762     }
2763 
2764     protected CmisTestResult assertEquals(PropertyDefinition<?> expected, PropertyDefinition<?> actual,
2765             CmisTestResult success, CmisTestResult failure) {
2766 
2767         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
2768 
2769         CmisTestResult f;
2770 
2771         if ((expected == null) && (actual == null)) {
2772             return success;
2773         }
2774 
2775         if (expected == null) {
2776             f = createResult(FAILURE, "Expected property defintion is null, but actual property defintion is not!");
2777             addResultChild(failure, f);
2778 
2779             return failure;
2780         }
2781 
2782         if (actual == null) {
2783             f = createResult(FAILURE, "Actual property defintion is null, but expected property defintion is not!");
2784             addResultChild(failure, f);
2785 
2786             return failure;
2787         }
2788 
2789         f = createResult(FAILURE, "Property ids don't match!");
2790         addResult(results, assertEquals(expected.getId(), actual.getId(), null, f));
2791 
2792         f = createResult(FAILURE, "Local names don't match!");
2793         addResult(results, assertEquals(expected.getLocalName(), actual.getLocalName(), null, f));
2794 
2795         f = createResult(FAILURE, "Local namespaces don't match!");
2796         addResult(results, assertEquals(expected.getLocalNamespace(), actual.getLocalNamespace(), null, f));
2797 
2798         f = createResult(FAILURE, "Display names don't match!");
2799         addResult(results, assertEquals(expected.getDisplayName(), actual.getDisplayName(), null, f));
2800 
2801         f = createResult(FAILURE, "Query names don't match!");
2802         addResult(results, assertEquals(expected.getQueryName(), actual.getQueryName(), null, f));
2803 
2804         f = createResult(FAILURE, "Property types don't match!");
2805         addResult(results, assertEquals(expected.getPropertyType(), actual.getPropertyType(), null, f));
2806 
2807         f = createResult(FAILURE, "Cardinalities don't match!");
2808         addResult(results, assertEquals(expected.getCardinality(), actual.getCardinality(), null, f));
2809 
2810         f = createResult(FAILURE, "Descriptions don't match!");
2811         addResult(results, assertEquals(expected.getDescription(), actual.getDescription(), null, f));
2812 
2813         f = createResult(FAILURE, "Updatability flags don't match!");
2814         addResult(results, assertEquals(expected.getUpdatability(), actual.getUpdatability(), null, f));
2815 
2816         f = createResult(FAILURE, "Default values don't match!");
2817         addResult(results, assertEqualLists(expected.getDefaultValue(), actual.getDefaultValue(), null, f));
2818 
2819         f = createResult(FAILURE, "Inherited flags don't match!");
2820         addResult(results, assertEquals(expected.isInherited(), actual.isInherited(), null, f));
2821 
2822         f = createResult(FAILURE, "Required flags don't match!");
2823         addResult(results, assertEquals(expected.isRequired(), actual.isRequired(), null, f));
2824 
2825         f = createResult(FAILURE, "Queryable flags don't match!");
2826         addResult(results, assertEquals(expected.isQueryable(), actual.isQueryable(), null, f));
2827 
2828         f = createResult(FAILURE, "Orderable flags don't match!");
2829         addResult(results, assertEquals(expected.isOrderable(), actual.isOrderable(), null, f));
2830 
2831         f = createResult(FAILURE, "Open choice flags don't match!");
2832         addResult(results, assertEquals(expected.isOpenChoice(), actual.isOpenChoice(), null, f));
2833 
2834         if (getWorst(results).getLevel() <= OK.getLevel()) {
2835             for (CmisTestResult result : results) {
2836                 addResultChild(success, result);
2837             }
2838 
2839             return success;
2840         } else {
2841             for (CmisTestResult result : results) {
2842                 addResultChild(failure, result);
2843             }
2844 
2845             return failure;
2846         }
2847     }
2848 
2849     protected CmisTestResult assertEquals(CmisObject expected, CmisObject actual, CmisTestResult success,
2850             CmisTestResult failure, boolean checkAcls, boolean checkPolicies) {
2851 
2852         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
2853 
2854         CmisTestResult f;
2855 
2856         if ((expected == null) && (actual == null)) {
2857             return success;
2858         }
2859 
2860         if (expected == null) {
2861             f = createResult(FAILURE, "Expected object is null, but actual object is not!");
2862             addResultChild(failure, f);
2863 
2864             return failure;
2865         }
2866 
2867         if (actual == null) {
2868             f = createResult(FAILURE, "Actual object is null, but expected object is not!");
2869             addResultChild(failure, f);
2870 
2871             return failure;
2872         }
2873 
2874         if (expected.getProperties().size() != actual.getProperties().size()) {
2875             f = createResult(FAILURE, "Number of properties don't match");
2876             addResult(results, assertEquals(expected.getProperties().size(), actual.getProperties().size(), null, f));
2877         } else {
2878             for (Property<?> expectedProperty : expected.getProperties()) {
2879                 Property<?> actualProperty = actual.getProperty(expectedProperty.getId());
2880 
2881                 f = createResult(FAILURE, "Properties don't match! Property: " + expectedProperty.getId());
2882                 addResult(results, assertEquals(expectedProperty, actualProperty, null, f));
2883             }
2884         }
2885 
2886         f = createResult(FAILURE, "Allowable actions don't match!");
2887         addResult(results, assertEquals(expected.getAllowableActions(), actual.getAllowableActions(), null, f));
2888 
2889         if (checkAcls) {
2890             f = createResult(FAILURE, "ACLs don't match!");
2891             addResult(results, assertEquals(expected.getAcl(), actual.getAcl(), null, f));
2892         }
2893 
2894         if (checkPolicies) {
2895             f = createResult(FAILURE, "Policies don't match!");
2896             addResult(results, assertEqualObjectList(expected.getPolicies(), actual.getPolicies(), null, f));
2897         }
2898 
2899         f = createResult(FAILURE, "Relationships don't match!");
2900         addResult(results, assertEqualObjectList(expected.getRelationships(), actual.getRelationships(), null, f));
2901 
2902         f = createResult(FAILURE, "Renditions don't match!");
2903         addResult(results, assertEqualRenditionLists(expected.getRenditions(), actual.getRenditions(), null, f));
2904 
2905         if (getWorst(results).getLevel() <= OK.getLevel()) {
2906             for (CmisTestResult result : results) {
2907                 addResultChild(success, result);
2908             }
2909 
2910             return success;
2911         } else {
2912             for (CmisTestResult result : results) {
2913                 addResultChild(failure, result);
2914             }
2915 
2916             return failure;
2917         }
2918     }
2919 
2920     protected CmisTestResult assertEqualObjectList(List<? extends CmisObject> expected,
2921             List<? extends CmisObject> actual, CmisTestResult success, CmisTestResult failure) {
2922 
2923         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
2924 
2925         CmisTestResult f;
2926 
2927         if ((expected == null) && (actual == null)) {
2928             return success;
2929         }
2930 
2931         if (expected == null) {
2932             f = createResult(FAILURE, "Expected list of CMIS objects is null, but actual list of CMIS objects is not!");
2933             addResultChild(failure, f);
2934 
2935             return failure;
2936         }
2937 
2938         if (actual == null) {
2939             f = createResult(FAILURE, "Actual list of CMIS objects is null, but expected list of CMIS objects is not!");
2940             addResultChild(failure, f);
2941 
2942             return failure;
2943         }
2944 
2945         if (expected.size() != actual.size()) {
2946             addResult(
2947                     results,
2948                     createResult(
2949                             CmisTestResultStatus.INFO,
2950                             "Object list sizes don't match! expected: " + expected.size() + " / actual: "
2951                                     + actual.size()));
2952         } else {
2953             for (int i = 0; i < expected.size(); i++) {
2954                 f = createResult(FAILURE, "Objects at position " + i + "  dont't match!");
2955                 addResult(results, assertEquals(expected.get(i), actual.get(i), null, f, true, false));
2956             }
2957         }
2958 
2959         if (getWorst(results).getLevel() <= OK.getLevel()) {
2960             for (CmisTestResult result : results) {
2961                 addResultChild(success, result);
2962             }
2963 
2964             return success;
2965         } else {
2966             for (CmisTestResult result : results) {
2967                 addResultChild(failure, result);
2968             }
2969 
2970             return failure;
2971         }
2972     }
2973 
2974     protected CmisTestResult assertEquals(Property<?> expected, Property<?> actual, CmisTestResult success,
2975             CmisTestResult failure) {
2976 
2977         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
2978 
2979         CmisTestResult f;
2980 
2981         if ((expected == null) && (actual == null)) {
2982             return success;
2983         }
2984 
2985         if (expected == null) {
2986             f = createResult(FAILURE, "Expected property is null, but actual property is not!");
2987             addResultChild(failure, f);
2988 
2989             return failure;
2990         }
2991 
2992         if (actual == null) {
2993             f = createResult(FAILURE, "Actual property is null, but expected property is not!");
2994             addResultChild(failure, f);
2995 
2996             return failure;
2997         }
2998 
2999         f = createResult(FAILURE, "Property definitions don't match!");
3000         addResult(results, assertEquals(expected.getDefinition(), actual.getDefinition(), null, f));
3001 
3002         f = createResult(FAILURE, "Property values don't match!");
3003         addResult(results, assertEqualLists(expected.getValues(), actual.getValues(), null, f));
3004 
3005         if (getWorst(results).getLevel() <= OK.getLevel()) {
3006             for (CmisTestResult result : results) {
3007                 addResultChild(success, result);
3008             }
3009 
3010             return success;
3011         } else {
3012             for (CmisTestResult result : results) {
3013                 addResultChild(failure, result);
3014             }
3015 
3016             return failure;
3017         }
3018     }
3019 
3020     protected CmisTestResult assertEquals(AllowableActions expected, AllowableActions actual, CmisTestResult success,
3021             CmisTestResult failure) {
3022 
3023         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
3024 
3025         CmisTestResult f;
3026 
3027         if ((expected == null) && (actual == null)) {
3028             return success;
3029         }
3030 
3031         if (expected == null) {
3032             f = createResult(FAILURE, "Expected allowable actions are null, but actual allowable actions are not!");
3033             addResultChild(failure, f);
3034 
3035             return failure;
3036         }
3037 
3038         if (actual == null) {
3039             f = createResult(FAILURE, "Actual allowable actions are null, but expected allowable actions are not!");
3040             addResultChild(failure, f);
3041 
3042             return failure;
3043         }
3044 
3045         f = createResult(FAILURE, "Allowable action sets don't match!");
3046         addResult(results, assertEqualSet(expected.getAllowableActions(), actual.getAllowableActions(), null, f));
3047 
3048         if (getWorst(results).getLevel() <= OK.getLevel()) {
3049             for (CmisTestResult result : results) {
3050                 addResultChild(success, result);
3051             }
3052 
3053             return success;
3054         } else {
3055             for (CmisTestResult result : results) {
3056                 addResultChild(failure, result);
3057             }
3058 
3059             return failure;
3060         }
3061     }
3062 
3063     protected CmisTestResult assertEquals(Acl expected, Acl actual, CmisTestResult success, CmisTestResult failure) {
3064 
3065         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
3066 
3067         CmisTestResult f;
3068 
3069         if ((expected == null) && (actual == null)) {
3070             return success;
3071         }
3072 
3073         if (expected == null) {
3074             f = createResult(FAILURE, "Expected ACL is null, but actual ACL is not!");
3075             addResultChild(failure, f);
3076 
3077             return failure;
3078         }
3079 
3080         if (actual == null) {
3081             f = createResult(FAILURE, "Actual ACL is null, but expected ACL is not!");
3082             addResultChild(failure, f);
3083 
3084             return failure;
3085         }
3086 
3087         f = createResult(FAILURE, "ACEs don't match!");
3088         addResult(results, assertEqualAceLists(expected.getAces(), actual.getAces(), null, f));
3089 
3090         f = createResult(FAILURE, "Exact flags dont't match!");
3091         addResult(results, assertEquals(expected.isExact(), actual.isExact(), null, f));
3092 
3093         if (getWorst(results).getLevel() <= OK.getLevel()) {
3094             for (CmisTestResult result : results) {
3095                 addResultChild(success, result);
3096             }
3097 
3098             return success;
3099         } else {
3100             for (CmisTestResult result : results) {
3101                 addResultChild(failure, result);
3102             }
3103 
3104             return failure;
3105         }
3106     }
3107 
3108     protected CmisTestResult assertEqualAceLists(List<Ace> expected, List<Ace> actual, CmisTestResult success,
3109             CmisTestResult failure) {
3110 
3111         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
3112 
3113         CmisTestResult f;
3114 
3115         if (expected == null && actual == null) {
3116             return success;
3117         }
3118 
3119         if (expected == null) {
3120             return addResultChild(failure, createResult(CmisTestResultStatus.INFO, "Expected ACE list is null!"));
3121         }
3122 
3123         if (actual == null) {
3124             return addResultChild(failure, createResult(CmisTestResultStatus.INFO, "Actual ACE list is null!"));
3125         }
3126 
3127         if (expected.size() != actual.size()) {
3128             addResult(
3129                     results,
3130                     createResult(CmisTestResultStatus.INFO, "ACE list sizes don't match! expected: " + expected.size()
3131                             + " / actual: " + actual.size()));
3132         } else {
3133             for (int i = 0; i < expected.size(); i++) {
3134                 f = createResult(FAILURE, "ACEs at position " + i + "  dont't match!");
3135                 addResult(results, assertEquals(expected.get(i), actual.get(i), null, f));
3136             }
3137         }
3138 
3139         if (getWorst(results).getLevel() <= OK.getLevel()) {
3140             for (CmisTestResult result : results) {
3141                 addResultChild(success, result);
3142             }
3143 
3144             return success;
3145         } else {
3146             for (CmisTestResult result : results) {
3147                 addResultChild(failure, result);
3148             }
3149 
3150             return failure;
3151         }
3152     }
3153 
3154     protected CmisTestResult assertEquals(Ace expected, Ace actual, CmisTestResult success, CmisTestResult failure) {
3155 
3156         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
3157 
3158         CmisTestResult f;
3159 
3160         if ((expected == null) && (actual == null)) {
3161             return success;
3162         }
3163 
3164         if (expected == null) {
3165             f = createResult(FAILURE, "Expected ACE is null, but actual ACE is not!");
3166             addResultChild(failure, f);
3167 
3168             return failure;
3169         }
3170 
3171         if (actual == null) {
3172             f = createResult(FAILURE, "Actual ACE is null, but expected ACE is not!");
3173             addResultChild(failure, f);
3174 
3175             return failure;
3176         }
3177 
3178         f = createResult(FAILURE, "Principal ids dont't match!");
3179         addResult(results, assertEquals(expected.getPrincipalId(), actual.getPrincipalId(), null, f));
3180 
3181         f = createResult(FAILURE, "Permissions dont't match!");
3182         addResult(results, assertEqualLists(expected.getPermissions(), actual.getPermissions(), null, f));
3183 
3184         if (getWorst(results).getLevel() <= OK.getLevel()) {
3185             for (CmisTestResult result : results) {
3186                 addResultChild(success, result);
3187             }
3188 
3189             return success;
3190         } else {
3191             for (CmisTestResult result : results) {
3192                 addResultChild(failure, result);
3193             }
3194 
3195             return failure;
3196         }
3197     }
3198 
3199     protected CmisTestResult assertEqualRenditionLists(List<Rendition> expected, List<Rendition> actual,
3200             CmisTestResult success, CmisTestResult failure) {
3201 
3202         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
3203 
3204         CmisTestResult f;
3205 
3206         if (expected == null && actual == null) {
3207             return success;
3208         }
3209 
3210         if (expected == null) {
3211             return addResultChild(failure, createResult(CmisTestResultStatus.INFO, "Expected rendition list is null!"));
3212         }
3213 
3214         if (actual == null) {
3215             return addResultChild(failure, createResult(CmisTestResultStatus.INFO, "Actual rendition list is null!"));
3216         }
3217 
3218         if (expected.size() != actual.size()) {
3219             addResult(
3220                     results,
3221                     createResult(
3222                             CmisTestResultStatus.INFO,
3223                             "Rendition list sizes don't match! expected: " + expected.size() + " / actual: "
3224                                     + actual.size()));
3225         } else {
3226             for (int i = 0; i < expected.size(); i++) {
3227                 f = createResult(FAILURE, "Renditions at position " + i + "  dont't match!");
3228                 addResult(results, assertEquals(expected.get(i), actual.get(i), null, f));
3229             }
3230         }
3231 
3232         if (getWorst(results).getLevel() <= OK.getLevel()) {
3233             for (CmisTestResult result : results) {
3234                 addResultChild(success, result);
3235             }
3236 
3237             return success;
3238         } else {
3239             for (CmisTestResult result : results) {
3240                 addResultChild(failure, result);
3241             }
3242 
3243             return failure;
3244         }
3245     }
3246 
3247     protected CmisTestResult assertEquals(Rendition expected, Rendition actual, CmisTestResult success,
3248             CmisTestResult failure) {
3249 
3250         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
3251 
3252         CmisTestResult f;
3253 
3254         if ((expected == null) && (actual == null)) {
3255             return success;
3256         }
3257 
3258         if (expected == null) {
3259             f = createResult(FAILURE, "Expected rendition is null, but actual rendition is not!");
3260             addResultChild(failure, f);
3261 
3262             return failure;
3263         }
3264 
3265         if (actual == null) {
3266             f = createResult(FAILURE, "Actual rendition is null, but expected rendition is not!");
3267             addResultChild(failure, f);
3268 
3269             return failure;
3270         }
3271 
3272         f = createResult(FAILURE, "Stream ids dont't match!");
3273         addResult(results, assertEquals(expected.getStreamId(), actual.getStreamId(), null, f));
3274 
3275         f = createResult(FAILURE, "Kinds dont't match!");
3276         addResult(results, assertEquals(expected.getKind(), actual.getKind(), null, f));
3277 
3278         f = createResult(FAILURE, "MIME types dont't match!");
3279         addResult(results, assertEquals(expected.getMimeType(), actual.getMimeType(), null, f));
3280 
3281         f = createResult(FAILURE, "Titles dont't match!");
3282         addResult(results, assertEquals(expected.getTitle(), actual.getTitle(), null, f));
3283 
3284         f = createResult(FAILURE, "Lengths dont't match!");
3285         addResult(results, assertEquals(expected.getLength(), actual.getLength(), null, f));
3286 
3287         f = createResult(FAILURE, "Heights dont't match!");
3288         addResult(results, assertEquals(expected.getBigHeight(), actual.getBigHeight(), null, f));
3289 
3290         f = createResult(FAILURE, "Widths dont't match!");
3291         addResult(results, assertEquals(expected.getBigWidth(), actual.getBigWidth(), null, f));
3292 
3293         f = createResult(FAILURE, "Rendition document ids dont't match!");
3294         addResult(results, assertEquals(expected.getRenditionDocumentId(), actual.getRenditionDocumentId(), null, f));
3295 
3296         if (getWorst(results).getLevel() <= OK.getLevel()) {
3297             for (CmisTestResult result : results) {
3298                 addResultChild(success, result);
3299             }
3300 
3301             return success;
3302         } else {
3303             for (CmisTestResult result : results) {
3304                 addResultChild(failure, result);
3305             }
3306 
3307             return failure;
3308         }
3309     }
3310 
3311     protected CmisTestResult assertEquals(ContentStream expected, ContentStream actual, CmisTestResult success,
3312             CmisTestResult failure) {
3313 
3314         List<CmisTestResult> results = new ArrayList<CmisTestResult>();
3315 
3316         CmisTestResult f;
3317 
3318         if ((expected == null) && (actual == null)) {
3319             return success;
3320         }
3321 
3322         if (expected == null) {
3323             f = createResult(FAILURE, "Expected stream is null, but actual stream is not!");
3324             addResultChild(failure, f);
3325 
3326             IOUtils.closeQuietly(actual);
3327 
3328             return failure;
3329         }
3330 
3331         if (actual == null) {
3332             f = createResult(FAILURE, "Actual object is null, but expected object is not!");
3333             addResultChild(failure, f);
3334 
3335             IOUtils.closeQuietly(expected);
3336 
3337             return failure;
3338         }
3339 
3340         f = createResult(WARNING, "Filenames don't match!");
3341         addResult(results, assertEquals(expected.getFileName(), actual.getFileName(), null, f));
3342 
3343         f = createResult(FAILURE, "MIME types don't match!");
3344         addResult(results, assertEquals(expected.getMimeType(), actual.getMimeType(), null, f));
3345 
3346         f = createResult(WARNING, "Lengths don't match!");
3347         addResult(results, assertEquals(expected.getBigLength(), actual.getBigLength(), null, f));
3348 
3349         boolean match = true;
3350 
3351         BufferedInputStream as = new BufferedInputStream(actual.getStream(), 64 * 1024);
3352         BufferedInputStream es = new BufferedInputStream(expected.getStream(), 64 * 1024);
3353 
3354         try {
3355             int ab = 0;
3356             int eb = 0;
3357 
3358             while (true) {
3359                 if (ab > -1) {
3360                     ab = as.read();
3361                 }
3362 
3363                 if (eb > -1) {
3364                     eb = es.read();
3365                 }
3366 
3367                 if (ab == -1 && eb == -1) {
3368                     break;
3369                 }
3370 
3371                 if (ab != eb) {
3372                     match = false;
3373                 }
3374             }
3375         } catch (Exception e) {
3376             f = createResult(UNEXPECTED_EXCEPTION, e.getMessage(), e, false);
3377             addResultChild(failure, f);
3378         }
3379 
3380         if (!match) {
3381             f = createResult(FAILURE, "Content streams don't match!");
3382             addResultChild(failure, f);
3383         }
3384 
3385         IOUtils.closeQuietly(as);
3386         IOUtils.closeQuietly(es);
3387 
3388         if (getWorst(results).getLevel() <= OK.getLevel()) {
3389             for (CmisTestResult result : results) {
3390                 addResultChild(success, result);
3391             }
3392 
3393             return success;
3394         } else {
3395             for (CmisTestResult result : results) {
3396                 addResultChild(failure, result);
3397             }
3398 
3399             return failure;
3400         }
3401     }
3402 
3403     // --- helpers ---
3404 
3405     protected void addResult(List<CmisTestResult> results, CmisTestResult result) {
3406         if (result != null) {
3407             if (result instanceof CmisTestResultImpl) {
3408                 ((CmisTestResultImpl) result).setStackTrace(getStackTrace());
3409             }
3410 
3411             results.add(result);
3412             if (result.isFatal()) {
3413                 throw new FatalTestException(result.getMessage());
3414             }
3415         }
3416     }
3417 
3418     protected CmisTestResultStatus getWorst(List<CmisTestResult> results) {
3419         if (isNullOrEmpty(results)) {
3420             return CmisTestResultStatus.OK;
3421         }
3422 
3423         int max = 0;
3424 
3425         for (CmisTestResult result : results) {
3426             if (max < result.getStatus().getLevel()) {
3427                 max = result.getStatus().getLevel();
3428             }
3429         }
3430 
3431         return CmisTestResultStatus.fromLevel(max);
3432     }
3433 
3434     // --- helper classes ---
3435 
3436     public class CmisPropertyDefintion {
3437         private final String id;
3438         private final Boolean required;
3439         private final PropertyType propertyType;
3440         private final Cardinality cardinality;
3441         private final Updatability updatability;
3442         private final Boolean queryable;
3443         private final Boolean orderable;
3444 
3445         public CmisPropertyDefintion(String id, Boolean required, PropertyType propertyType, Cardinality cardinality,
3446                 Updatability updatability, Boolean queryable, Boolean orderable) {
3447             this.id = id;
3448             this.required = required;
3449             this.propertyType = propertyType;
3450             this.cardinality = cardinality;
3451             this.updatability = updatability;
3452             this.queryable = queryable;
3453             this.orderable = (cardinality == Cardinality.MULTI ? Boolean.FALSE : orderable);
3454         }
3455 
3456         public CmisTestResult check(TypeDefinition type) {
3457             List<CmisTestResult> results = new ArrayList<CmisTestResult>();
3458 
3459             CmisTestResult f;
3460 
3461             Map<String, PropertyDefinition<?>> propDefs = type.getPropertyDefinitions();
3462             if (propDefs == null) {
3463                 addResult(results, createResult(FAILURE, "Property definitions are missing!"));
3464             } else {
3465                 PropertyDefinition<?> propDef = propDefs.get(id);
3466                 if (propDef == null) {
3467                     addResult(results, createResult(FAILURE, "Property definition is missing!"));
3468                 } else {
3469                     if ((required != null) && !required.equals(propDef.isRequired())) {
3470                         f = createResult(FAILURE,
3471                                 "Required flag: expected: " + required + " / actual: " + propDef.isRequired());
3472                         addResult(results, f);
3473                     }
3474 
3475                     if (!propertyType.equals(propDef.getPropertyType())) {
3476                         f = createResult(FAILURE,
3477                                 "Property type: expected: " + propertyType + " / actual: " + propDef.getPropertyType());
3478                         addResult(results, f);
3479                     }
3480 
3481                     if (!cardinality.equals(propDef.getCardinality())) {
3482                         f = createResult(FAILURE,
3483                                 "Cardinality: expected: " + cardinality + " / actual: " + propDef.getCardinality());
3484                         addResult(results, f);
3485                     }
3486 
3487                     if ((updatability != null) && !updatability.equals(propDef.getUpdatability())) {
3488                         f = createResult(FAILURE,
3489                                 "Updatability: expected: " + updatability + " / actual: " + propDef.getUpdatability());
3490                         addResult(results, f);
3491                     }
3492 
3493                     if ((queryable != null) && !queryable.equals(propDef.isQueryable())) {
3494                         f = createResult(FAILURE,
3495                                 "Queryable: expected: " + queryable + " / actual: " + propDef.isQueryable());
3496                         addResult(results, f);
3497                     }
3498 
3499                     boolean isPropertyQueryNameRequired = Boolean.TRUE.equals(queryable);
3500                     checkQueryName(propDef.getQueryName(), isPropertyQueryNameRequired, "Property Query Name: "
3501                             + propDef.getQueryName());
3502 
3503                     if ((orderable != null) && !orderable.equals(propDef.isOrderable())) {
3504                         f = createResult(FAILURE,
3505                                 "Orderable: expected: " + orderable + " / actual: " + propDef.isOrderable());
3506                         addResult(results, f);
3507                     }
3508 
3509                     if (type.getBaseTypeId() != null) {
3510                         Boolean inherited = !type.getBaseTypeId().value().equals(type.getId());
3511                         if (!inherited.equals(propDef.isInherited())) {
3512                             f = createResult(FAILURE,
3513                                     "Inhertited: expected: " + inherited + " / actual: " + propDef.isInherited());
3514                             addResult(results, f);
3515                         }
3516                     }
3517 
3518                     // data type specific tests
3519                     if (propDef instanceof PropertyStringDefinition) {
3520                         PropertyStringDefinition stringPropDef = (PropertyStringDefinition) propDef;
3521 
3522                         if (stringPropDef.getMaxLength() != null) {
3523                             if (stringPropDef.getMaxLength().signum() == 0) {
3524                                 f = createResult(WARNING, "Max length is 0!");
3525                                 addResult(results, f);
3526                             } else if (stringPropDef.getMaxLength().signum() == -1) {
3527                                 f = createResult(FAILURE, "Max length is negative!");
3528                                 addResult(results, f);
3529                             }
3530                         }
3531                     } else if (propDef instanceof PropertyIntegerDefinition) {
3532                         PropertyIntegerDefinition intPropDef = (PropertyIntegerDefinition) propDef;
3533 
3534                         if (intPropDef.getMinValue() != null & intPropDef.getMaxValue() != null) {
3535                             if (intPropDef.getMinValue().compareTo(intPropDef.getMaxValue()) == 0) {
3536                                 f = createResult(WARNING, "Min and max values are equal!");
3537                                 addResult(results, f);
3538                             } else if (intPropDef.getMinValue().compareTo(intPropDef.getMaxValue()) == 1) {
3539                                 f = createResult(FAILURE, "Min value is greater than max value!");
3540                                 addResult(results, f);
3541                             }
3542                         }
3543                     } else if (propDef instanceof PropertyDecimalDefinition) {
3544                         PropertyDecimalDefinition decPropDef = (PropertyDecimalDefinition) propDef;
3545 
3546                         if (decPropDef.getMinValue() != null & decPropDef.getMaxValue() != null) {
3547                             if (decPropDef.getMinValue().compareTo(decPropDef.getMaxValue()) == 0) {
3548                                 f = createResult(WARNING, "Min and max values are equal!");
3549                                 addResult(results, f);
3550                             } else if (decPropDef.getMinValue().compareTo(decPropDef.getMaxValue()) == 1) {
3551                                 f = createResult(FAILURE, "Min value is greater than max value!");
3552                                 addResult(results, f);
3553                             }
3554                         }
3555                     }
3556                 }
3557             }
3558 
3559             CmisTestResultImpl result = createResult(getWorst(results), "Property definition: " + id);
3560             result.getChildren().addAll(results);
3561 
3562             return (result.getStatus().getLevel() <= OK.getLevel() ? null : result);
3563         }
3564     }
3565 }