This project has retired. For details please refer to its Attic page.
AbstractSessionTest xref

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