/* * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> * * $Id$ */ package org.eclipse.ecr.core.storage.sql; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.ecr.core.api.Blob; import org.eclipse.ecr.core.api.DocumentModel; import org.eclipse.ecr.core.api.blobholder.BlobHolderAdapterService; import org.eclipse.ecr.core.api.externalblob.ExternalBlobAdapter; import org.eclipse.ecr.core.api.externalblob.FileSystemExternalBlobAdapter; import org.eclipse.ecr.core.api.impl.blob.StringBlob; import org.eclipse.ecr.core.api.model.Property; import org.eclipse.ecr.core.api.model.impl.primitives.ExternalBlobProperty; import org.eclipse.ecr.core.schema.SchemaManager; import org.eclipse.ecr.core.schema.types.Field; import org.eclipse.ecr.core.schema.types.ListType; import org.eclipse.ecr.core.schema.types.Type; import org.eclipse.ecr.core.storage.sql.testlib.SQLRepositoryTestCase; import org.eclipse.ecr.runtime.api.Framework; /** * @author Anahide Tchertchian * */ @SuppressWarnings("unchecked") public class TestSQLRepositoryProperties extends SQLRepositoryTestCase { public static final String TEST_BUNDLE = "org.eclipse.ecr.core.storage.sql.test"; DocumentModel doc; public TestSQLRepositoryProperties(String name) { super(name); } @Override public void setUp() throws Exception { super.setUp(); deployContrib(TEST_BUNDLE, "OSGI-INF/test-repo-core-types-contrib.xml"); // deploy specific adapter for testing external blobs: files are stored // in temporary directory deployContrib(TEST_BUNDLE, "OSGI-INF/test-externalblob-adapters-contrib.xml"); // set container to temp directory here in case that depends on the OS // or machine configuration and add funny characters to avoid problems // due to xml parsing BlobHolderAdapterService service = Framework.getService(BlobHolderAdapterService.class); assertNotNull(service); ExternalBlobAdapter adapter = service.getExternalBlobAdapterForPrefix("fs"); Map<String, String> props = new HashMap<String, String>(); props.put(FileSystemExternalBlobAdapter.CONTAINER_PROPERTY_NAME, "\n" + System.getProperty("java.io.tmpdir") + " "); adapter.setProperties(props); openSession(); doc = session.createDocumentModel("TestDocument"); doc.setPathInfo("/", "doc"); doc = session.createDocument(doc); } protected File createTempFile() throws Exception { File file = File.createTempFile("testExternalBlob", ".txt"); FileWriter fstream = new FileWriter(file); BufferedWriter out = new BufferedWriter(fstream); out.write("Hello External Blob"); out.close(); file.deleteOnExit(); return file; } // NXP-2467 public void testCreationWithDefaultPrefetch() throws Exception { DocumentModel doc = session.createDocumentModel("TestDocumentWithDefaultPrefetch"); doc.setPathInfo("/", "docwithDefaultPrefetch"); session.createDocument(doc); } public void testStringArray() throws Exception { assertNotNull(doc.getPropertyValue("tp:stringArray")); String[] values = { "foo", "bar" }; doc.setPropertyValue("tp:stringArray", values); doc = session.saveDocument(doc); assertTrue(Arrays.equals(values, (Object[]) doc.getPropertyValue("tp:stringArray"))); } // NXP-2454 public void testDateArray() throws Exception { assertNotNull(doc.getPropertyValue("tp:dateArray")); Calendar cal = Calendar.getInstance(); cal.set(2008, 6, 10); Calendar[] values = { cal }; doc.setPropertyValue("tp:dateArray", values); doc = session.saveDocument(doc); // currently returning long[] instead of Calendar[] assertTrue(Arrays.equals(values, (Object[]) doc.getPropertyValue("tp:dateArray"))); } // NXP-2454 public void testIntArray() throws Exception { assertNotNull(doc.getPropertyValue("tp:intArray")); Long[] values = { 1L, 2L, 3L }; doc.setPropertyValue("tp:intArray", values); doc = session.saveDocument(doc); // currently returning long[], maybe this is the wanted behaviour (?) assertTrue(Arrays.equals(values, (Object[]) doc.getPropertyValue("tp:intArray"))); } public void testComplexList() throws Exception { // not null on list assertTrue(doc.getPropertyValue("tp:complexList") instanceof List); assertEquals(0, ((List) doc.getPropertyValue("tp:complexList")).size()); ArrayList<Map<String, Serializable>> values = new ArrayList<Map<String, Serializable>>(); Map<String, Serializable> item = new HashMap<String, Serializable>(); item.put("string", "foo"); Calendar cal = Calendar.getInstance(); cal.set(2008, 6, 10); item.put("date", cal); item.put("int", 3L); values.add(item); doc.setPropertyValue("tp:complexList", values); doc = session.saveDocument(doc); Serializable actual = doc.getPropertyValue("tp:complexList"); assertTrue(actual instanceof List); assertEquals(1, ((List) actual).size()); assertEquals(item, ((List) actual).get(0)); } // NXP-912 public void testNewBlob() throws Exception { // simple Object value = null; SchemaManager tm = Framework.getService(SchemaManager.class); Field field = tm.getField("tp:fileList"); Type type = field.getType(); Type itemType = ((ListType) type).getFieldType(); value = itemType.newInstance(); assertNull(value); // complex field = tm.getField("tp:fileComplexList"); type = field.getType(); itemType = ((ListType) type).getFieldType(); Map<String, Serializable> map = (Map) itemType.newInstance(); assertEquals(2, map.size()); assertTrue(map.containsKey("filename")); assertTrue(map.containsKey("blob")); assertNull(map.get("filename")); assertNull(map.get("blob")); } // NXP-2468 public void testBlobListValue() throws Exception { // not null on list assertTrue(doc.getPropertyValue("tp:fileList") instanceof List); assertEquals(0, ((List) doc.getPropertyValue("tp:fileList")).size()); ArrayList<Blob> values = new ArrayList<Blob>(); StringBlob blob = new StringBlob("My content"); values.add(blob); doc.setPropertyValue("tp:fileList", values); doc = session.saveDocument(doc); Serializable actual = doc.getPropertyValue("tp:fileList"); assertTrue(actual instanceof List); List<Blob> blobs = (List) actual; assertEquals(1, blobs.size()); assertNotNull(blobs.get(0)); } // NXP-2301 public void testSubBlobValue() throws Exception { // not null on list assertTrue(doc.getPropertyValue("tp:fileComplexList") instanceof List); assertEquals(0, ((List) doc.getPropertyValue("tp:fileComplexList")).size()); ArrayList<Map<String, Serializable>> values = new ArrayList<Map<String, Serializable>>(); Map<String, Serializable> item = new HashMap<String, Serializable>(); StringBlob blob = new StringBlob("My content"); item.put("blob", blob); item.put("filename", "My filename"); values.add(item); doc.setPropertyValue("tp:fileComplexList", values); doc = session.saveDocument(doc); Object actual = doc.getPropertyValue("tp:fileComplexList"); assertTrue(actual instanceof List); List<Map<String, Serializable>> items = (List) actual; assertEquals(1, items.size()); assertNotNull(items.get(0)); Map<String, Serializable> actualItem = items.get(0); assertEquals("My filename", actualItem.get("filename")); assertTrue(actualItem.get("blob") instanceof Blob); Object actualBlob = doc.getProperty("tp:fileComplexList/0/blob").getValue( Blob.class); assertTrue(actualBlob instanceof Blob); } public void testComplexPropertyChain() throws Exception { Property p = doc.getProperty("tp:complexChain"); assertTrue(p.getValue() instanceof Map); assertEquals(2, ((Map) p.getValue()).size()); p.setValue("string", "test"); Map<String, Serializable> map = new HashMap<String, Serializable>(); map.put("string", "test2"); p.setValue("complex", map); doc = session.saveDocument(doc); p = doc.getProperty("tp:complexChain"); assertTrue(p.getValue() instanceof Map); assertEquals("test", p.getValue("string")); assertEquals("test2", p.getValue("complex/string")); p = p.get("complex"); assertTrue(p.getValue() instanceof Map); assertEquals("test2", p.getValue("string")); } public void testComplexPropertySubValue() throws Exception { doc.setPropertyValue("tp:complex/string", "test"); doc = session.saveDocument(doc); assertEquals("test", doc.getPropertyValue("tp:complex/string")); } // NXP-2318: i don't get what's supposed to be answered to these questions public void XXXtestArrayOrListProperties() throws Exception { Property prop = doc.getProperty("tp:stringArray"); assertFalse(prop.isContainer()); assertFalse(prop.isList()); assertTrue(prop.isScalar()); prop = doc.getProperty("tp:dateArray"); assertFalse(prop.isContainer()); assertFalse(prop.isList()); assertTrue(prop.isScalar()); prop = doc.getProperty("tp:intArray"); assertFalse(prop.isContainer()); assertFalse(prop.isList()); assertTrue(prop.isScalar()); prop = doc.getProperty("tp:complex"); assertTrue(prop.isContainer()); assertFalse(prop.isList()); assertFalse(prop.isScalar()); prop = doc.getProperty("tp:complexList"); assertTrue(prop.isContainer()); assertTrue(prop.isList()); assertFalse(prop.isScalar()); } public void testExternalBlobDocumentProperty() throws Exception { File file = createTempFile(); HashMap<String, String> map = new HashMap<String, String>(); String uri = String.format("fs:%s", file.getName()); map.put(ExternalBlobProperty.URI, uri); map.put(ExternalBlobProperty.FILE_NAME, "hello.txt"); doc.setPropertyValue("tp:externalcontent", map); doc = session.saveDocument(doc); Object blob = doc.getPropertyValue("tp:externalcontent"); assertNotNull(blob); assertTrue(blob instanceof Blob); assertEquals("Hello External Blob", ((Blob) blob).getString()); assertEquals("hello.txt", ((Blob) blob).getFilename()); assertEquals("hello.txt", doc.getPropertyValue("tp:externalcontent/name")); assertEquals(uri, doc.getPropertyValue("tp:externalcontent/uri")); } // this time only set the uri public void testExternalBlobDocumentProperty2() throws Exception { File file = createTempFile(); String uri = String.format("fs:%s", file.getName()); doc.setPropertyValue("tp:externalcontent/uri", uri); doc = session.saveDocument(doc); Object blob = doc.getPropertyValue("tp:externalcontent"); assertNotNull(blob); assertTrue(blob instanceof Blob); assertEquals("Hello External Blob", ((Blob) blob).getString()); assertEquals(file.getName(), ((Blob) blob).getFilename()); assertNull(doc.getPropertyValue("tp:externalcontent/name")); assertEquals(uri, doc.getPropertyValue("tp:externalcontent/uri")); } // NXP-2468 public void testExternalBlobListValue() throws Exception { // not null on list String propName = "tp:externalFileList"; assertTrue(doc.getPropertyValue(propName) instanceof List); assertEquals(0, ((List) doc.getPropertyValue(propName)).size()); File file = createTempFile(); ArrayList<Map> values = new ArrayList<Map>(); Map<String, String> map = new HashMap<String, String>(); String uri = String.format("fs:%s", file.getName()); map.put(ExternalBlobProperty.URI, uri); map.put(ExternalBlobProperty.FILE_NAME, "hello.txt"); values.add(map); doc.setPropertyValue(propName, values); doc = session.saveDocument(doc); Serializable actual = doc.getPropertyValue(propName); assertTrue(actual instanceof List); List<Blob> blobs = (List) actual; assertEquals(1, blobs.size()); assertNotNull(blobs.get(0)); assertTrue(blobs.get(0) instanceof Blob); Blob actualBlob = blobs.get(0); assertEquals("Hello External Blob", actualBlob.getString()); assertEquals("hello.txt", actualBlob.getFilename()); assertEquals("hello.txt", doc.getPropertyValue(propName + "/0/name")); assertEquals(uri, doc.getPropertyValue(propName + "/0/uri")); } // NXP-2301 public void testSubExternalBlobValue() throws Exception { String propName = "tp:externalFileComplexList"; // not null on list assertTrue(doc.getPropertyValue(propName) instanceof List); assertEquals(0, ((List) doc.getPropertyValue(propName)).size()); ArrayList<Map<String, Serializable>> values = new ArrayList<Map<String, Serializable>>(); Map<String, Serializable> item = new HashMap<String, Serializable>(); File file = createTempFile(); HashMap<String, String> blobMap = new HashMap<String, String>(); String uri = String.format("fs:%s", file.getName()); blobMap.put(ExternalBlobProperty.URI, uri); blobMap.put(ExternalBlobProperty.FILE_NAME, "hello.txt"); item.put("blob", blobMap); item.put("filename", "My filename"); values.add(item); doc.setPropertyValue(propName, values); doc = session.saveDocument(doc); Object actual = doc.getPropertyValue(propName); assertTrue(actual instanceof List); List<Map<String, Serializable>> items = (List) actual; assertEquals(1, items.size()); assertNotNull(items.get(0)); Map<String, Serializable> actualItem = items.get(0); assertEquals("My filename", actualItem.get("filename")); assertTrue(actualItem.get("blob") instanceof Blob); Object actualBlob = doc.getProperty(propName + "/0/blob").getValue(); assertTrue(actualBlob instanceof Blob); assertEquals("Hello External Blob", ((Blob) actualBlob).getString()); assertEquals("hello.txt", ((Blob) actualBlob).getFilename()); assertEquals("hello.txt", doc.getPropertyValue(propName + "/0/blob/name")); assertEquals(uri, doc.getPropertyValue(propName + "/0/blob/uri")); } public void testSaveComplexTwice() throws Exception { testComplexList(); doc.setPropertyValue("tp:stringArray", new String[] {}); // dirty dp doc = session.saveDocument(doc); // rewrites complex list again session.save(); } // not many tests, logs have to be looked at to confirm behavior public void testUpdateMinimalChanges() throws Exception { // populate some properties testStringArray(); testDateArray(); testComplexList(); testBlobListValue(); session.save(); closeSession(); openSession(); // change just one of the collection properties doc.setPropertyValue("tp:stringArray", new String[] { "baz" }); doc = session.saveDocument(doc); session.save(); // check that the minimal number of updates are done in the db } }