001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2008
005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
006: * All rights reserved
007: *
008: * The [fleXive](R) project is free software; you can redistribute
009: * it and/or modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation;
011: * either version 2 of the License, or (at your option) any
012: * later version.
013: *
014: * The GNU General Public License can be found at
015: * http://www.gnu.org/copyleft/gpl.html.
016: * A copy is found in the textfile GPL.txt and important notices to the
017: * license from the author are found in LICENSE.txt distributed with
018: * these libraries.
019: *
020: * This library is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024: *
025: * For further information about UCS - unique computing solutions gmbh,
026: * please see the company website: http://www.ucs.at
027: *
028: * For further information about [fleXive](R), please see the
029: * project website: http://www.flexive.org
030: *
031: *
032: * This copyright notice MUST APPEAR in all copies of the file!
033: ***************************************************************/package com.flexive.tests.embedded.structure;
034:
035: import com.flexive.shared.CacheAdmin;
036: import com.flexive.shared.content.FxContent;
037: import com.flexive.shared.content.FxPK;
038: import com.flexive.shared.exceptions.FxApplicationException;
039: import com.flexive.shared.exceptions.FxLogoutFailedException;
040: import com.flexive.shared.exceptions.FxNotFoundException;
041: import com.flexive.shared.exceptions.FxRemoveException;
042: import com.flexive.shared.security.ACL;
043: import com.flexive.shared.structure.*;
044: import com.flexive.shared.value.FxString;
045: import com.flexive.tests.embedded.FxTestUtils;
046: import static com.flexive.tests.embedded.FxTestUtils.login;
047: import static com.flexive.tests.embedded.FxTestUtils.logout;
048: import com.flexive.tests.embedded.TestUsers;
049: import org.apache.commons.lang.RandomStringUtils;
050: import org.testng.annotations.AfterClass;
051: import org.testng.annotations.BeforeClass;
052: import org.testng.annotations.Test;
053:
054: /**
055: * Tests for structure inheritance
056: *
057: * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
058: */
059: @Test(groups={"ejb","structure"})
060: public class InheritanceTest extends StructureTestBase {
061:
062: private final static String TYPE_NAME = "INHERITANCETEST_"
063: + RandomStringUtils.random(16, true, true);
064:
065: private ACL aclStructure, aclWorkflow, aclContent;
066: private long typeId;
067:
068: private void createBaseProperty(String name, String XPath)
069: throws FxApplicationException {
070: ass.createProperty(typeId, FxPropertyEdit.createNew(name,
071: new FxString("InheritanceTest UnitTest property "
072: + name), new FxString("hint..."),
073: FxMultiplicity.MULT_0_1, aclStructure,
074: FxDataType.String1024), XPath);
075: }
076:
077: private void createDerivedProperty(long typeId, String name,
078: String XPath) throws FxApplicationException {
079: ass.createProperty(typeId, FxPropertyEdit.createNew(name,
080: new FxString("InheritanceTest UnitTest property "
081: + name), new FxString("hint..."),
082: FxMultiplicity.MULT_0_1, aclStructure,
083: FxDataType.String1024), XPath);
084: }
085:
086: private void createBaseGroup(String name, String XPath,
087: GroupMode mode) throws FxApplicationException {
088: ass.createGroup(typeId, FxGroupEdit.createNew(name,
089: new FxString("InheritanceTest UnitTest group " + name),
090: new FxString("hint..."), true, FxMultiplicity.MULT_0_1)
091: .setAssignmentGroupMode(mode), XPath);
092: }
093:
094: private void createDerivedGroup(long typeId, String name,
095: String XPath, GroupMode mode) throws FxApplicationException {
096: ass.createGroup(typeId, FxGroupEdit.createNew(name,
097: new FxString("InheritanceTest UnitTest group " + name),
098: new FxString("hint..."), true, FxMultiplicity.MULT_0_1)
099: .setAssignmentGroupMode(mode), XPath);
100: }
101:
102: /**
103: * setup...
104: *
105: * @throws Exception on errors
106: */
107: @BeforeClass
108: public void beforeClass() throws Exception {
109: super .init();
110: login(TestUsers.SUPERVISOR);
111: //create the base type
112: ACL[] tmp = FxTestUtils.createACLs(
113: new String[] {
114: "STRUCTURE_"
115: + RandomStringUtils.random(16, true,
116: true),
117: "WORKFLOW_"
118: + RandomStringUtils.random(16, true,
119: true),
120: "CONTENT_"
121: + RandomStringUtils.random(16, true,
122: true)
123:
124: }, new ACL.Category[] { ACL.Category.STRUCTURE,
125: ACL.Category.WORKFLOW, ACL.Category.INSTANCE },
126: TestUsers.getTestMandator());
127: aclStructure = tmp[0];
128: aclWorkflow = tmp[1];
129: aclContent = tmp[2];
130: typeId = type.save(FxTypeEdit.createNew(TYPE_NAME,
131: new FxString("Test data"), aclStructure, null));
132:
133: /*
134: type
135: +- A_P1
136: +- B
137: | +-B_P1
138: | +-B_P2
139: +-C
140: +-C_P1
141: +-C_G1
142: +- C_G1_P1
143: +- C_G1_P2
144: */
145:
146: createBaseProperty("A_P1", "/");
147:
148: createBaseGroup("B", "/", GroupMode.AnyOf);
149: createBaseProperty("B_P1", "/B");
150: createBaseProperty("B_P2", "/B");
151:
152: createBaseGroup("C", "/", GroupMode.AnyOf);
153: createBaseGroup("C_G1", "/C", GroupMode.AnyOf);
154: createBaseProperty("C_G1_P1", "/C/C_G1");
155: createBaseProperty("C_G1_P2", "/C/C_G1");
156: createBaseProperty("C_P1", "/C");
157: }
158:
159: @AfterClass(dependsOnMethods={"tearDownStructures"})
160: public void afterClass() throws FxLogoutFailedException,
161: FxApplicationException {
162: logout();
163: }
164:
165: @AfterClass
166: public void tearDownStructures() throws Exception {
167: long typeId = CacheAdmin.getEnvironment().getType(TYPE_NAME)
168: .getId();
169: co.removeForType(typeId);
170: type.remove(typeId);
171: FxTestUtils.removeACL(aclStructure, aclWorkflow, aclContent);
172: }
173:
174: /**
175: * Test directly derived type
176: *
177: * @throws Exception on errors
178: */
179: public void directDerivedType() throws Exception {
180: String DERIVED_NAME = "DERIVED_"
181: + RandomStringUtils.random(5, true, true);
182: FxTypeEdit te = FxTypeEdit.createNew(DERIVED_NAME,
183: new FxString("Description..."), aclStructure,
184: CacheAdmin.getEnvironment().getType(TYPE_NAME));
185: long derivedId = -1;
186: try {
187: derivedId = type.save(te);
188: FxType derived = CacheAdmin.getEnvironment().getType(
189: DERIVED_NAME);
190: checkDerived(derived, "/A_P1", "/B", "/B/B_P1", "/B/B_P2",
191: "/C", "/C/C_P1", "/C/C_G1", "/C/C_G1/C_G1_P1",
192: "/C/C_G1/C_G1_P2");
193: //disable a derived assignment and test vs the parent type
194: FxContent pc = co.initialize(typeId);
195: FxContent dc = co.initialize(derivedId);
196: FxString data = new FxString(false, "abc");
197: final String TEST_XPATH = "/C/C_G1/C_G1_P1";
198: pc.setValue(TEST_XPATH, data);
199: dc.setValue(TEST_XPATH, data);
200: FxPK pk_p = co.save(pc);
201: FxPK pk_d = co.save(dc);
202: FxPropertyAssignmentEdit fxa_d = new FxPropertyAssignmentEdit(
203: (FxPropertyAssignment) derived
204: .getAssignment("/C/C_G1/C_G1_P1"));
205: fxa_d.setEnabled(false);
206: ass.save(fxa_d, false);
207: derived = CacheAdmin.getEnvironment().getType(DERIVED_NAME);
208: assert !derived.getAssignment(TEST_XPATH).isEnabled() : "Expected ["
209: + TEST_XPATH + "] to be disabled!";
210: FxContent dc_dis = co.load(pk_d);
211: pc = co.load(pk_p);
212: try {
213: dc_dis.getPropertyData(TEST_XPATH);
214: assert false : TEST_XPATH
215: + " should not exist after being disabled!";
216: } catch (FxNotFoundException e) {
217: //expected!
218: }
219: assert pc.getPropertyData(TEST_XPATH).getValue().equals(
220: data) : "Wrong data for parent instance!";
221: //disable /B and subgroups
222: FxGroupAssignmentEdit fxg_d = new FxGroupAssignmentEdit(
223: (FxGroupAssignment) derived.getAssignment("/B"));
224: fxg_d.setEnabled(false);
225: ass.save(fxg_d, false);
226: derived = CacheAdmin.getEnvironment().getType(DERIVED_NAME);
227: String[] tests = { "/B", "/B/B_P1", "/B/B_P2" };
228: for (String xpath : tests)
229: assert !derived.getAssignment(xpath).isEnabled() : "Expected ["
230: + xpath + "] to be disabled!";
231: //enable again
232: fxg_d = new FxGroupAssignmentEdit(
233: (FxGroupAssignment) derived.getAssignment("/B"));
234: fxg_d.setEnabled(true);
235: ass.save(fxg_d, false);
236: derived = CacheAdmin.getEnvironment().getType(DERIVED_NAME);
237: for (String xpath : tests)
238: assert derived.getAssignment(xpath).isEnabled() : "Expected ["
239: + xpath + "] to be enabled!";
240: } finally {
241: if (derivedId != -1) {
242: co.removeForType(derivedId);
243: type.remove(derivedId);
244: }
245: }
246: }
247:
248: /**
249: * Test inheritance of assignments in inherited types of inherited types
250: *
251: * @throws Exception on errors
252: */
253: public void assignmentInheritance() throws Exception {
254: /*
255: type
256: +- A_P1
257: +- A_P2 <-- added in 1st inheritance, should exist in 2nd
258: +- B
259: | +-B_P1
260: | +-B_P2
261: | +-B_P3 <-- added in 1st inheritance, should exist in 2nd
262: +-C
263: | +-C_P1
264: | +-C_G1
265: | | +- C_G1_P1
266: | | +- C_G1_P2
267: | +-C_G2 <-- added in 1st inheritance, should exist in 2nd
268: | +- C_G2_P1 <-- added in 1st inheritance, should exist in 2nd
269: +-D <-- added in 1st inheritance, should exist in 2nd
270: +-D_P1 <-- added in 1st inheritance, should exist in 2nd
271: */
272: final String DERIVED1_NAME = "DERIVED1_"
273: + RandomStringUtils.random(5, true, true);
274: final String DERIVED2_NAME = "DERIVED2_"
275: + RandomStringUtils.random(5, true, true);
276: long derived1Id = -1;
277: long derived2Id = -1;
278: try {
279: derived1Id = type.save(FxTypeEdit.createNew(DERIVED1_NAME,
280: new FxString("Description1..."), aclStructure,
281: CacheAdmin.getEnvironment().getType(TYPE_NAME)));
282: derived2Id = type
283: .save(FxTypeEdit.createNew(DERIVED2_NAME,
284: new FxString("Description2..."),
285: aclStructure, CacheAdmin.getEnvironment()
286: .getType(DERIVED1_NAME)));
287: derivedSubCheck("/A_P2", derived1Id, DERIVED1_NAME,
288: DERIVED2_NAME);
289: derivedSubCheck("/B/B_P3", derived1Id, DERIVED1_NAME,
290: DERIVED2_NAME);
291: createDerivedGroup(derived1Id, "C_G2", "/C",
292: GroupMode.AnyOf);
293: derivedSubCheck("/C/C_G2/C_G2_P1", derived1Id,
294: DERIVED1_NAME, DERIVED2_NAME);
295: createDerivedGroup(derived1Id, "D", "/", GroupMode.AnyOf);
296: derivedSubCheck("/D/D_P1", derived1Id, DERIVED1_NAME,
297: DERIVED2_NAME);
298: //Add A_P3 to the base type
299: createBaseProperty("A_P3", "/");
300: checkDerived(CacheAdmin.getEnvironment().getType(
301: DERIVED1_NAME), "/A_P3");
302: checkDerived(CacheAdmin.getEnvironment().getType(
303: DERIVED2_NAME), "/A_P3");
304: FxType base = CacheAdmin.getEnvironment()
305: .getType(TYPE_NAME);
306: long ap3_id = base.getAssignment("/A_P3").getId();
307: //remove A_P3 from base type, 'breaking' inheritance and making derived1 the new parent of this property
308: ass.removeAssignment(ap3_id, true, false);
309: FxPropertyAssignment pa_d1 = (FxPropertyAssignment) CacheAdmin
310: .getEnvironment().getAssignment(
311: DERIVED1_NAME + "/A_P3");
312: FxPropertyAssignment pa_d2 = (FxPropertyAssignment) CacheAdmin
313: .getEnvironment().getAssignment(
314: DERIVED2_NAME + "/A_P3");
315: assert !pa_d1.isDerivedAssignment() : DERIVED1_NAME
316: + "/A_P3 must not be a derived assignment!";
317: assert pa_d2.isDerivedAssignment() : DERIVED2_NAME
318: + "/A_P3 expected be a derived assignment!";
319: assert pa_d2.getBaseAssignmentId() == pa_d1.getId() : "Expected "
320: + DERIVED2_NAME
321: + "/A_P3 to be derived from "
322: + DERIVED1_NAME + "/A_P3!";
323: } finally {
324: if (derived2Id != -1) {
325: co.removeForType(derived2Id);
326: type.remove(derived2Id);
327: }
328: if (derived1Id != -1) {
329: co.removeForType(derived1Id);
330: type.remove(derived1Id);
331: }
332: }
333: }
334:
335: /**
336: * Check if a derived type has really inherited the test property
337: *
338: * @param testProperty XPath of the property to test
339: * @param derived1Id id of the type derived from the "base" type
340: * @param DERIVED1_NAME name of the type derived from the "base" type
341: * @param DERIVED2_NAME name of the type derived from derived1
342: * @throws FxApplicationException on errors
343: */
344: private void derivedSubCheck(String testProperty, long derived1Id,
345: String DERIVED1_NAME, String DERIVED2_NAME)
346: throws FxApplicationException {
347: createDerivedProperty(derived1Id, testProperty
348: .substring(testProperty.lastIndexOf("/") + 1),
349: testProperty.substring(0, (testProperty
350: .lastIndexOf("/") > 0 ? testProperty
351: .lastIndexOf("/") : 1)));
352: FxType derived1 = CacheAdmin.getEnvironment().getType(
353: DERIVED1_NAME);
354: try {
355: assert derived1.getAssignment(testProperty) instanceof FxPropertyAssignment : "Expected "
356: + testProperty + " to be a property assignment!";
357: } catch (Exception e) {
358: assert false : "Failed to lookup " + testProperty
359: + " in derived1 type! msg=" + e.getClass() + ":"
360: + e.getMessage();
361: }
362: FxType derived2 = CacheAdmin.getEnvironment().getType(
363: DERIVED2_NAME);
364: checkDerived(derived2, testProperty); //should exist for derived2 as well!
365: }
366:
367: /**
368: * Check if the given xpath's are marked as derived and not removeable
369: *
370: * @param derived the type to check against
371: * @param xpaths xpath's that have to be derived
372: * @throws FxApplicationException on errors
373: */
374: private void checkDerived(FxType derived, String... xpaths)
375: throws FxApplicationException {
376: for (String xpath : xpaths) {
377: FxAssignment fxa = derived.getAssignment(xpath);
378: assert fxa.isDerivedAssignment() : "Expected [" + xpath
379: + "] to be a derived assignment!";
380: try {
381: ass.removeAssignment(fxa.getId(), true, false);
382: assert false : "Removal of derived assignment ["
383: + xpath + "] should not be possible!";
384: } catch (FxApplicationException e) {
385: if (!(e instanceof FxRemoveException))
386: throw e;
387: }
388: }
389: }
390:
391: }
|