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