View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.chemistry.opencmis.tck.tests.types;
20  
21  import static org.apache.chemistry.opencmis.tck.CmisTestResultStatus.FAILURE;
22  import static org.apache.chemistry.opencmis.tck.CmisTestResultStatus.SKIPPED;
23  
24  import java.util.Collections;
25  import java.util.HashSet;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Set;
29  
30  import org.apache.chemistry.opencmis.client.api.Document;
31  import org.apache.chemistry.opencmis.client.api.Folder;
32  import org.apache.chemistry.opencmis.client.api.ObjectId;
33  import org.apache.chemistry.opencmis.client.api.ObjectType;
34  import org.apache.chemistry.opencmis.client.api.Property;
35  import org.apache.chemistry.opencmis.client.api.SecondaryType;
36  import org.apache.chemistry.opencmis.client.api.Session;
37  import org.apache.chemistry.opencmis.commons.PropertyIds;
38  import org.apache.chemistry.opencmis.commons.definitions.DocumentTypeDefinition;
39  import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
40  import org.apache.chemistry.opencmis.commons.enums.Action;
41  import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
42  import org.apache.chemistry.opencmis.commons.enums.Updatability;
43  import org.apache.chemistry.opencmis.tck.CmisTestResult;
44  import org.apache.chemistry.opencmis.tck.impl.AbstractSessionTest;
45  
46  public class SecondaryTypesTest extends AbstractSessionTest {
47      @Override
48      public void init(Map<String, String> parameters) {
49          super.init(parameters);
50          setName("Secondary Types Test");
51          setDescription("Creates documents, attaches and detaches secondary types, checks the properties, and finally deletes the test documents.");
52      }
53  
54      @Override
55      public void run(Session session) {
56          if (session.getRepositoryInfo().getCmisVersion() == CmisVersion.CMIS_1_0) {
57              addResult(createResult(SKIPPED, "Secondary types are not supported by CMIS 1.0. Test skipped!"));
58              return;
59          }
60  
61          if (!hasSecondaries(session)) {
62              addResult(createResult(SKIPPED, "Repository doesn't support secondary types. Test skipped!"));
63              return;
64          }
65  
66          // check cmis:secondaryObjectTypeIds property definition
67          ObjectType docType = session.getTypeDefinition(getDocumentTestTypeId());
68          PropertyDefinition<?> secTypesPropDef = docType.getPropertyDefinitions().get(
69                  PropertyIds.SECONDARY_OBJECT_TYPE_IDS);
70          if (secTypesPropDef == null) {
71              addResult(createResult(FAILURE, "Test document type has no " + PropertyIds.SECONDARY_OBJECT_TYPE_IDS
72                      + " property!"));
73              return;
74          } else if (secTypesPropDef.getUpdatability() != Updatability.READWRITE) {
75              addResult(createResult(SKIPPED,
76                      "Test document type does not allow attaching secondary types. Test skipped!"));
77              return;
78          }
79  
80          // create a test folder
81          Folder testFolder = createTestFolder(session);
82  
83          try {
84              String secondaryTestTypeId = getSecondaryTestTypeId();
85              ObjectType secondaryTestType = session.getTypeDefinition(secondaryTestTypeId);
86  
87              createDocumentAndAttachSecondaryType(session, testFolder, secondaryTestType);
88              createDocumentWithSecondaryType(session, testFolder, secondaryTestType);
89          } finally {
90              // delete the test folder
91              deleteTestFolder();
92          }
93      }
94  
95      private void createDocumentAndAttachSecondaryType(Session session, Folder testFolder, ObjectType secondaryTestType) {
96          Document doc = createDocument(session, testFolder, "createandattach.txt", "Secondary Type Test");
97          Document workDoc = doc;
98  
99          try {
100             // test if check out is required
101             boolean checkedout = false;
102             if (needsCheckOut(doc)) {
103                 workDoc = (Document) session.getObject(doc.checkOut(), SELECT_ALL_NO_CACHE_OC);
104                 checkedout = true;
105             }
106 
107             // attach secondary type
108             ObjectId newId = workDoc.updateProperties(null, Collections.singletonList(secondaryTestType.getId()), null);
109             Document newDoc = (Document) session.getObject(newId, SELECT_ALL_NO_CACHE_OC);
110 
111             // check if the secondary type is there
112             boolean found = checkSecondaryType(newDoc, secondaryTestType);
113 
114             // -- detach secondary type
115             if (found) {
116                 detachSecondaryType(session, newDoc, secondaryTestType);
117             }
118 
119             // cancel a possible check out
120             if (checkedout) {
121                 workDoc.cancelCheckOut();
122             }
123         } finally {
124             deleteObject(doc);
125         }
126     }
127 
128     private void createDocumentWithSecondaryType(Session session, Folder testFolder, ObjectType secondaryTestType) {
129         Document doc = createDocument(session, testFolder, "createwithsecondarytype.txt", getDocumentTestTypeId(),
130                 new String[] { secondaryTestType.getId() }, "Secondary Type Test");
131 
132         try {
133             // check if the secondary type is there
134             boolean found = checkSecondaryType(doc, secondaryTestType);
135 
136             // detach secondary type
137             if (found && !needsCheckOut(doc)) {
138                 detachSecondaryType(session, doc, secondaryTestType);
139             }
140         } finally {
141             deleteObject(doc);
142         }
143     }
144 
145     private boolean needsCheckOut(Document doc) {
146         DocumentTypeDefinition type = (DocumentTypeDefinition) doc.getType();
147         PropertyDefinition<?> secTypeIdsPropDef = type.getPropertyDefinitions().get(
148                 PropertyIds.SECONDARY_OBJECT_TYPE_IDS);
149 
150         return secTypeIdsPropDef.getUpdatability() == Updatability.WHENCHECKEDOUT
151                 || (!doc.getAllowableActions().getAllowableActions().contains(Action.CAN_UPDATE_PROPERTIES) && Boolean.TRUE
152                         .equals(type.isVersionable()));
153     }
154 
155     private boolean checkSecondaryType(Document doc, ObjectType secondaryTestType) {
156         CmisTestResult f;
157 
158         // check if the secondary type is there
159         boolean found = false;
160         if (doc.getSecondaryTypes() == null) {
161             addResult(createResult(FAILURE, "Document does not have the attached secondary type!"));
162         } else {
163             for (SecondaryType secType : doc.getSecondaryTypes()) {
164                 if (secondaryTestType.getId().equals(secType.getId())) {
165                     found = true;
166                     break;
167                 }
168             }
169 
170             f = createResult(FAILURE, "Document does not have the attached secondary type!");
171             addResult(assertIsTrue(found, null, f));
172         }
173 
174         // check properties of secondary type
175         if (found) {
176             Set<String> secondaryTypeProperties = new HashSet<String>();
177 
178             if (secondaryTestType.getPropertyDefinitions() != null) {
179                 for (PropertyDefinition<?> propDef : secondaryTestType.getPropertyDefinitions().values()) {
180                     secondaryTypeProperties.add(propDef.getId());
181                 }
182             }
183 
184             for (Property<?> prop : doc.getProperties()) {
185                 secondaryTypeProperties.remove(prop.getId());
186             }
187 
188             f = createResult(FAILURE, "Documents lacks the following secondary type properties: "
189                     + secondaryTypeProperties);
190             addResult(assertIsTrue(secondaryTypeProperties.isEmpty(), null, f));
191         }
192 
193         return found;
194     }
195 
196     private void detachSecondaryType(Session session, Document doc, ObjectType secondaryTestType) {
197         CmisTestResult f;
198 
199         // detach secondary type
200         ObjectId newId = doc.updateProperties(null, null, Collections.singletonList(secondaryTestType.getId()));
201         Document newDoc = (Document) session.getObject(newId, SELECT_ALL_NO_CACHE_OC);
202 
203         boolean found = false;
204         if (newDoc.getSecondaryTypes() != null) {
205             for (SecondaryType secType : newDoc.getSecondaryTypes()) {
206                 if (secondaryTestType.getId().equals(secType.getId())) {
207                     found = true;
208                     break;
209                 }
210             }
211         }
212 
213         f = createResult(FAILURE, "Document still has the detached secondary type!");
214         addResult(assertIsFalse(found, null, f));
215 
216         // check properties
217         ObjectType primaryType = newDoc.getType();
218         List<SecondaryType> secondaryTypes = newDoc.getSecondaryTypes();
219 
220         for (Property<?> prop : doc.getProperties()) {
221             if (!primaryType.getPropertyDefinitions().containsKey(prop.getId())) {
222                 f = createResult(FAILURE, "Property '" + prop.getId()
223                         + "' is neither defined by the primary type nor by a secondary type!");
224 
225                 if (secondaryTypes == null) {
226                     addResult(f);
227                 } else {
228                     boolean foundProperty = false;
229                     for (SecondaryType secondaryType : secondaryTypes) {
230                         if (secondaryType.getPropertyDefinitions() != null
231                                 && secondaryType.getPropertyDefinitions().containsKey(prop.getId())) {
232                             foundProperty = true;
233                             break;
234                         }
235                     }
236                     addResult(assertIsTrue(foundProperty, null, f));
237                 }
238             }
239         }
240     }
241 }