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;
034:
035: import com.flexive.shared.CacheAdmin;
036: import com.flexive.shared.EJBLookup;
037: import com.flexive.shared.FxLanguage;
038: import com.flexive.shared.content.FxContent;
039: import com.flexive.shared.content.FxPK;
040: import com.flexive.shared.exceptions.FxApplicationException;
041: import com.flexive.shared.exceptions.FxLogoutFailedException;
042: import com.flexive.shared.interfaces.AssignmentEngine;
043: import com.flexive.shared.interfaces.ContentEngine;
044: import com.flexive.shared.interfaces.TypeEngine;
045: import com.flexive.shared.security.ACL;
046: import com.flexive.shared.structure.*;
047: import com.flexive.shared.value.*;
048: import static com.flexive.tests.embedded.FxTestUtils.login;
049: import static com.flexive.tests.embedded.FxTestUtils.logout;
050: import org.apache.commons.lang.RandomStringUtils;
051: import org.apache.commons.lang.StringUtils;
052: import org.testng.annotations.AfterClass;
053: import org.testng.annotations.BeforeClass;
054: import org.testng.annotations.Test;
055:
056: import java.io.File;
057: import java.io.FileInputStream;
058: import java.io.FileOutputStream;
059: import java.util.*;
060:
061: /**
062: * Tests for FxValues (single/multi language, store/load)
063: *
064: * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
065: */
066: @Test(groups={"ejb","valuetest"})
067: public class ValueTest {
068:
069: private ContentEngine co;
070: private TypeEngine type;
071: private AssignmentEngine ass;
072:
073: private final static String TYPE_NAME = "TESTVALUES_"
074: + RandomStringUtils.random(16, true, true);
075:
076: private ACL aclStructure, aclWorkflow, aclContent;
077: private long typeId;
078: private FxType REF_TYPE1, REF_TYPE2;
079: private FxPK RPK1, RPK2;
080:
081: /**
082: * setup...
083: *
084: * @throws Exception on errors
085: */
086: @BeforeClass
087: public void beforeClass() throws Exception {
088: co = EJBLookup.getContentEngine();
089: type = EJBLookup.getTypeEngine();
090: ass = EJBLookup.getAssignmentEngine();
091: login(TestUsers.SUPERVISOR);
092: //create the base type
093: ACL[] tmp = FxTestUtils.createACLs(
094: new String[] {
095: "STRUCTURE_"
096: + RandomStringUtils.random(16, true,
097: true),
098: "WORKFLOW_"
099: + RandomStringUtils.random(16, true,
100: true),
101: "CONTENT_"
102: + RandomStringUtils.random(16, true,
103: true)
104:
105: }, new ACL.Category[] { ACL.Category.STRUCTURE,
106: ACL.Category.WORKFLOW, ACL.Category.INSTANCE },
107: TestUsers.getTestMandator());
108: aclStructure = tmp[0];
109: aclWorkflow = tmp[1];
110: aclContent = tmp[2];
111:
112: typeId = type.save(FxTypeEdit.createNew(TYPE_NAME,
113: new FxString("Test data"), aclStructure, null));
114:
115: //create referenced types
116: long rt1 = type.save(FxTypeEdit.createNew(
117: "Referenced Test Type 1", new FxString("Test data"),
118: aclStructure, null));
119: REF_TYPE1 = CacheAdmin.getEnvironment().getType(rt1);
120: long rt2 = type.save(FxTypeEdit.createNew(
121: "Referenced Test Type 2", new FxString("Test data"),
122: aclStructure, null));
123: REF_TYPE2 = CacheAdmin.getEnvironment().getType(rt2);
124: //create single test entries for both referenced types
125: FxContent co1 = co.initialize(REF_TYPE1.getId());
126: RPK1 = new FxPK(co.save(co1).getId(), 1); //fix to set it to max version instead of specific
127: FxContent co2 = co.initialize(REF_TYPE2.getId());
128: RPK2 = new FxPK(co.save(co2).getId(), 1); //fix to set it to max version instead of specific
129: }
130:
131: private void createProperty(FxDataType dataType)
132: throws FxApplicationException {
133: FxPropertyEdit prop = FxPropertyEdit.createNew(
134: "VTS" + dataType.name(),
135: new FxString("UnitTest for " + dataType.name()),
136: new FxString("hint..."), new FxMultiplicity(1, 1),
137: aclStructure, dataType).setMultiLang(false)
138: .setOverrideMultiLang(true);
139: switch (dataType) {
140: case Reference:
141: prop.setReferencedType(REF_TYPE1);
142: break;
143: default:
144: //nothing
145: }
146: long propId = ass.createProperty(typeId, prop, "/");
147: FxPropertyAssignment paSingle = (FxPropertyAssignment) CacheAdmin
148: .getEnvironment().getAssignment(propId);
149: FxPropertyAssignmentEdit pe = FxPropertyAssignmentEdit
150: .createNew(paSingle, paSingle.getAssignedType(),
151: "VTM" + dataType.name(), "/")
152: .setMultiLang(true);
153: ass.save(pe, false);
154: }
155:
156: private void removeProperty(FxDataType dataType)
157: throws FxApplicationException {
158: long assId = CacheAdmin.getEnvironment().getAssignment(
159: TYPE_NAME.toUpperCase() + "/VTS"
160: + dataType.name().toUpperCase()).getId();
161: ass.removeAssignment(assId, true, true);
162: }
163:
164: @AfterClass(dependsOnMethods={"tearDownStructures"})
165: public void afterClass() throws FxLogoutFailedException,
166: FxApplicationException {
167: logout();
168: }
169:
170: @AfterClass
171: public void tearDownStructures() throws Exception {
172: long typeId = CacheAdmin.getEnvironment().getType(TYPE_NAME)
173: .getId();
174: co.removeForType(typeId);
175: type.remove(typeId);
176: co.remove(RPK1);
177: co.remove(RPK2);
178: type.remove(REF_TYPE1.getId());
179: type.remove(REF_TYPE2.getId());
180: FxTestUtils.removeACL(aclStructure, aclWorkflow, aclContent);
181: }
182:
183: class TestData<T extends FxValue> {
184: FxDataType dataType;
185: T _single;
186: T _multi;
187: Object en_value;
188: Object de_value;
189:
190: public TestData(FxDataType dataType, T _single, T _multi) {
191: assert !_single.isMultiLanguage() : "1st value argument has to be single language!";
192: assert _multi.isMultiLanguage() : "2nd value argument has to be multi language!";
193: this .dataType = dataType;
194: this ._single = _single;
195: this ._multi = _multi;
196: en_value = _single.getBestTranslation();
197: de_value = _multi.getBestTranslation();
198: this ._single.setTranslation(FxLanguage.ENGLISH, en_value);
199: this ._multi.setTranslation(FxLanguage.ENGLISH, en_value);
200: this ._multi.setTranslation(FxLanguage.GERMAN, de_value);
201: this ._multi.setDefaultLanguage(FxLanguage.ENGLISH);
202: }
203:
204: public void testConsistency() throws Exception {
205: assert !_single.equals(_multi);
206: assert _single.getDefaultTranslation().equals(
207: _multi.getDefaultTranslation());
208: assert _multi.getTranslation(FxLanguage.ENGLISH).equals(
209: en_value);
210: assert _multi.getTranslation(FxLanguage.GERMAN).equals(
211: de_value);
212: assert _multi.getTranslatedLanguages().length == 2;
213: assert _single.getTranslatedLanguages().length == 1;
214: assert _single.getTranslation(FxLanguage.GERMAN).equals(
215: en_value);
216: _single.setTranslation(FxLanguage.ENGLISH, de_value);
217: assert _single.getTranslation(FxLanguage.GERMAN).equals(
218: de_value);
219: _single.setDefaultLanguage(FxLanguage.ITALIAN);
220: assert !_single.hasDefaultLanguage();
221: assert _single.getTranslation(FxLanguage.ENGLISH).equals(
222: de_value);
223: assert _multi.hasDefaultLanguage();
224: //TODO: more asserts for standard behaviour ...
225: }
226:
227: public void testSingleValue(FxValue compare) throws Exception {
228: if (compare instanceof FxBinary) {
229: BinaryDescriptor desc = ((FxBinary) compare)
230: .getBestTranslation();
231: assert desc.isImage() : "Expected an image!";
232: assert desc.getWidth() == 2048 : "Wrong image width!";
233: assert desc.getHeight() == 1536 : "Wrong image height!";
234: assert desc.getResolution() == 72.0
235: || desc.getResolution() == 180.0 : "Wrong image resolution! Expected [72.0] or [180.0] depending on ImageMagick version but got ["
236: + desc.getResolution() + "]";
237: //download
238: File f = File.createTempFile("FxBinary", ".bin");
239: FileOutputStream fout = new FileOutputStream(f);
240: System.out.println("b4 download of "
241: + f.getAbsolutePath() + " ...");
242: long time = System.currentTimeMillis();
243: ((FxBinary) compare).getBestTranslation()
244: .download(fout);
245: System.out
246: .println("download of " + f.getAbsolutePath()
247: + " took "
248: + (System.currentTimeMillis() - time)
249: + "[ms]!");
250: fout.close();
251: f.deleteOnExit();
252: return;
253: } else if (compare instanceof FxHTML) {
254: assert ((String) compare.getBestTranslation())
255: .indexOf((String) _single.getBestTranslation()) >= 0 : "Original single value was not found in tidied value!";
256: return;
257: }
258: //cant use regular compare since even single language values will be loaded as multi language if the assignment is multilinugual!
259: assert _single.getBestTranslation().equals(
260: compare.getBestTranslation()) : _single.getClass()
261: .getCanonicalName()
262: + " mismatch for single language value (DataType "
263: + dataType.name()
264: + "): "
265: + _single.toString()
266: + "!=" + compare.toString();
267: }
268:
269: public void testMultiValue(FxValue compare) throws Exception {
270: if (compare instanceof FxBinary)
271: return; //cant test this yet
272: // else if( compare instanceof FxHTML ) {
273: // return;
274: // }
275: assert _multi.equals(compare) : _multi.getClass()
276: .getCanonicalName()
277: + " mismatch for multi language value (DataType "
278: + dataType.name()
279: + "): "
280: + _multi.toString()
281: + "!=" + compare.toString();
282: }
283: }
284:
285: @Test
286: public void valueTest() throws Exception {
287: GregorianCalendar gc_multi_date = new GregorianCalendar(1940,
288: 11, 22);
289: GregorianCalendar gc_multi_date2 = new GregorianCalendar(1997,
290: 9, 21);
291: GregorianCalendar gc_single_date = new GregorianCalendar(1974,
292: 0, 12);
293: GregorianCalendar gc_single_date2 = new GregorianCalendar(1974,
294: 3, 17);
295: GregorianCalendar gc_multi_datetime = new GregorianCalendar(
296: 1940, 11, 22, 3, 30, 20);
297: GregorianCalendar gc_multi_datetime2 = new GregorianCalendar(
298: 1997, 9, 21, 7, 40, 30);
299: GregorianCalendar gc_single_datetime = new GregorianCalendar(
300: 1974, 0, 12, 4, 35, 45);
301: GregorianCalendar gc_single_datetime2 = new GregorianCalendar(
302: 1974, 3, 17, 14, 30, 15);
303: String s_single = "ABC";
304: String s_multi = "DEF";
305:
306: File testFile = new File("test.file");
307: if (!testFile.exists())
308: testFile = new File(
309: "src/framework/testresources/image/Exif.JPG");
310: if (!testFile.exists())
311: return;
312: FileInputStream fis = new FileInputStream(testFile);
313: long time = System.currentTimeMillis();
314: BinaryDescriptor binary = new BinaryDescriptor(testFile
315: .getName(), testFile.length(), fis);
316: System.out.println("size: " + binary.getSize() + " time: "
317: + (System.currentTimeMillis() - time));
318:
319: System.out.println("==valueTest== Handle received for "
320: + binary.getName() + ": " + binary.getHandle());
321: fis.close();
322:
323: TestData[] data = {
324: new TestData<FxHTML>(FxDataType.HTML, new FxHTML(false,
325: s_single).setTidyHTML(true), new FxHTML(true,
326: s_multi)),
327:
328: new TestData<FxString>(FxDataType.String1024,
329: new FxString(false, s_single), new FxString(
330: true, s_multi)),
331:
332: new TestData<FxString>(FxDataType.Text, new FxString(
333: false, s_single), new FxString(true, s_multi)),
334:
335: new TestData<FxNumber>(FxDataType.Number, new FxNumber(
336: false, Integer.MAX_VALUE), new FxNumber(true,
337: Integer.MIN_VALUE)),
338:
339: new TestData<FxLargeNumber>(FxDataType.LargeNumber,
340: new FxLargeNumber(false, Long.MAX_VALUE),
341: new FxLargeNumber(true, Long.MIN_VALUE)),
342:
343: new TestData<FxFloat>(FxDataType.Float, new FxFloat(
344: false, Float.MAX_VALUE), new FxFloat(true,
345: Float.MIN_VALUE)),
346:
347: new TestData<FxDouble>(FxDataType.Double, new FxDouble(
348: false, 1E300), new FxDouble(true, 1E-300)),
349:
350: new TestData<FxBoolean>(FxDataType.Boolean,
351: new FxBoolean(false, true), new FxBoolean(true,
352: false)),
353:
354: new TestData<FxDate>(FxDataType.Date, new FxDate(false,
355: gc_single_date.getTime()), new FxDate(true,
356: gc_multi_date.getTime())),
357:
358: new TestData<FxDateTime>(FxDataType.DateTime,
359: new FxDateTime(false, gc_single_datetime
360: .getTime()), new FxDateTime(true,
361: gc_multi_datetime.getTime())),
362:
363: new TestData<FxDateRange>(FxDataType.DateRange,
364: new FxDateRange(false, new DateRange(
365: gc_single_date.getTime(),
366: gc_single_date2.getTime())),
367: new FxDateRange(true, new DateRange(
368: gc_multi_date.getTime(), gc_multi_date2
369: .getTime()))),
370:
371: new TestData<FxDateTimeRange>(FxDataType.DateTimeRange,
372: new FxDateTimeRange(false, new DateRange(
373: gc_single_datetime.getTime(),
374: gc_single_datetime2.getTime())),
375: new FxDateTimeRange(true, new DateRange(
376: gc_multi_datetime.getTime(),
377: gc_multi_datetime2.getTime()))),
378:
379: new TestData<FxBinary>(FxDataType.Binary, new FxBinary(
380: false, binary), new FxBinary(true, binary)),
381:
382: new TestData<FxReference>(FxDataType.Reference,
383: new FxReference(false, new ReferencedContent(
384: RPK1)), new FxReference(true,
385: new ReferencedContent(RPK1))) };
386: FxType testType;
387: StringBuilder sbErr = new StringBuilder(100);
388: for (TestData test : data) {
389: try {
390: System.out.println("Testing " + test.dataType.name()
391: + " ...");
392: test.testConsistency();
393: createProperty(test.dataType);
394: testType = CacheAdmin.getEnvironment().getType(
395: TYPE_NAME);
396: FxContent content = co.initialize(testType.getId());
397: content.setValue("/VTS" + test.dataType.name() + "[1]",
398: test._single.copy());
399: // content.getPropertyData("/VT" + test.dataType.name() + "[1]").createNew(FxPropertyData.POSITION_BOTTOM);
400: content.setValue("/VTM" + test.dataType.name() + "[1]",
401: test._multi.copy());
402: FxPK pk = co.save(content);
403: FxContent loaded = co.load(pk);
404: test.testSingleValue(loaded.getPropertyData(
405: "/VTS" + test.dataType.name() + "[1]")
406: .getValue());
407: test.testMultiValue(loaded.getPropertyData(
408: "/VTM" + test.dataType.name() + "[1]")
409: .getValue());
410: pk = co.save(loaded);
411: loaded = co.load(pk);
412: test.testSingleValue(loaded.getPropertyData(
413: "/VTS" + test.dataType.name() + "[1]")
414: .getValue());
415: test.testMultiValue(loaded.getPropertyData(
416: "/VTM" + test.dataType.name() + "[1]")
417: .getValue());
418: co.remove(pk);
419: if (test.dataType == FxDataType.Reference) {
420: //additional tests
421: content = co.initialize(testType.getId());
422: try {
423: //set to a new pk
424: content.setValue("/VTS" + test.dataType.name()
425: + "[1]", new FxReference(
426: new ReferencedContent(new FxPK())));
427: co.save(content); //expected to fail
428: assert false : "Invalid PK (new) for a reference should fail!";
429: } catch (FxApplicationException e) {
430: //expected
431: }
432: try {
433: //set to a non existing pk
434: content.setValue("/VTS" + test.dataType.name()
435: + "[1]",
436: new FxReference(new ReferencedContent(
437: new FxPK(123456))));
438: co.save(content); //expected to fail
439: assert false : "Invalid PK (non existant) for a reference should fail!";
440: } catch (FxApplicationException e) {
441: //expected
442: }
443: try {
444: //set to an existing pk, but wrong type
445: content.setValue("/VTS" + test.dataType.name()
446: + "[1]", new FxReference(
447: new ReferencedContent(RPK2)));
448: co.save(content); //expected to fail
449: assert false : "Invalid PK (wrong type) for a reference should fail!";
450: } catch (FxApplicationException e) {
451: //expected
452: }
453: }
454: } catch (Throwable e) {
455: sbErr.append("Failed DataType: [").append(
456: test.dataType.name()).append("] with: ")
457: .append(e.getMessage()).append("\n");
458: e.printStackTrace();
459: } finally {
460: removeProperty(test.dataType);
461: }
462: }
463: if (sbErr.length() > 0)
464: assert false : sbErr.toString();
465: }
466:
467: /**
468: * Basic tests of FxValue's {@link Comparable} implementation
469: */
470: @Test
471: public void compareToTest() {
472: final List<FxString> strings = new ArrayList<FxString>(Arrays
473: .asList(new FxString("b"), new FxString("a"),
474: new FxString("c"), new FxString("a0")));
475: Collections.sort(strings);
476: final String sortedStrings = StringUtils.join(strings
477: .iterator(), ',');
478: assert sortedStrings.equals("a,a0,b,c") : "Expected lexical order 'a,a0,b,c', got: "
479: + sortedStrings;
480: }
481: }
|