/* * Copyright (C) 2005-2010 Alfresco Software Limited. * * This file is part of Alfresco * * Alfresco is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ package org.alfresco.repo.version; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.alfresco.model.ApplicationModel; import org.alfresco.model.ContentModel; import org.alfresco.repo.cache.TransactionalCache; import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.Path; import org.alfresco.service.cmr.version.Version; import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.util.debug.NodeStoreInspector; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * @author Roy Wetherall */ public class NodeServiceImplTest extends BaseVersionStoreTest { private static Log logger = LogFactory.getLog(NodeServiceImplTest.class); /** * version store node service */ protected NodeService versionStoreNodeService = null; /** * Error message */ private final static String MSG_ERR = "This operation is not supported by a version store implementation of the node service."; /** * Dummy data used in failure tests */ private NodeRef dummyNodeRef = null; private QName dummyQName = null; /** * Called during the transaction setup */ protected void onSetUpInTransaction() throws Exception { super.onSetUpInTransaction(); // Get the node service by name this.versionStoreNodeService = (NodeService)this.applicationContext.getBean("versionNodeService"); // Create some dummy data used during the tests this.dummyNodeRef = new NodeRef( this.versionService.getVersionStoreReference(), "dummy"); this.dummyQName = QName.createQName("{dummy}dummy"); } /** * Test getType */ public void testGetType() { // Create a new versionable node NodeRef versionableNode = createNewVersionableNode(); // Create a new version Version version = createVersion(versionableNode, this.versionProperties); // Get the type from the versioned state QName versionedType = this.versionStoreNodeService.getType(version.getFrozenStateNodeRef()); assertNotNull(versionedType); assertEquals(this.dbNodeService.getType(versionableNode), versionedType); } /** * Test getProperties */ public void testGetProperties() { // Create a new versionable node NodeRef versionableNode = createNewVersionableNode(); // Get a list of the nodes properties Map origProps = this.dbNodeService.getProperties(versionableNode); // Create a new version Version version = createVersion(versionableNode, this.versionProperties); // Get the properties of the versioned state Map versionedProperties = this.versionStoreNodeService.getProperties(version.getFrozenStateNodeRef()); if (logger.isDebugEnabled()) { logger.debug("original ("+origProps.size()+"): " + origProps.keySet()); logger.debug("versioned ("+versionedProperties.size()+"): " + versionedProperties.keySet()); } for (QName key : origProps.keySet()) { assertTrue(versionedProperties.containsKey(key)); assertEquals(""+key, origProps.get(key), versionedProperties.get(key)); } // NOTE: cm:versionLabel is an expected additional property //assertEquals(origProps.size(), versionedProperties.size()); // check version label assertEquals("first version label", "0.1", versionedProperties.get(ContentModel.PROP_VERSION_LABEL)); // TODO do futher versioning and check by changing values } /** * Test getProperty */ public void testGetProperty() { // Create a new versionable node NodeRef versionableNode = createNewVersionableNode(); // Create a new version Version version = createVersion(versionableNode, this.versionProperties); // Check the property values can be retrieved Serializable value1 = this.versionStoreNodeService.getProperty( version.getFrozenStateNodeRef(), PROP_1); assertEquals(VALUE_1, value1); // Check the mlText property // TODO // Check the multi values property specifically Collection multiValue = (Collection)this.versionStoreNodeService.getProperty(version.getFrozenStateNodeRef(), MULTI_PROP); assertNotNull(multiValue); assertEquals(2, multiValue.size()); String[] array = multiValue.toArray(new String[multiValue.size()]); assertEquals(MULTI_VALUE_1, array[0]); assertEquals(MULTI_VALUE_2, array[1]); } /** * Test getChildAssocs */ public void testGetChildAssocs() { if (logger.isTraceEnabled()) { // Let's have a look at the version store .. logger.trace(NodeStoreInspector.dumpNodeStore( this.dbNodeService, this.versionService.getVersionStoreReference()) + "\n\n"); logger.trace(""); } // Create a new versionable node NodeRef versionableNode = createNewVersionableNode(); Collection originalChildren = this.dbNodeService.getChildAssocs(versionableNode); assertNotNull(originalChildren); // Store the original children in a map for easy navigation later HashMap originalChildAssocRefs = new HashMap(); for (ChildAssociationRef ref : originalChildren) { originalChildAssocRefs.put(ref.getChildRef().getId(), ref); } // Create a new version Version version = createVersion(versionableNode, this.versionProperties); if (logger.isTraceEnabled()) { // Let's have a look at the version store .. logger.trace(NodeStoreInspector.dumpNodeStore( this.dbNodeService, this.versionService.getVersionStoreReference())); logger.trace(""); } // Get the children of the versioned node Collection versionedChildren = this.versionStoreNodeService.getChildAssocs(version.getFrozenStateNodeRef()); assertNotNull(versionedChildren); assertEquals(originalChildren.size(), versionedChildren.size()); for (ChildAssociationRef versionedChildRef : versionedChildren) { ChildAssociationRef origChildAssocRef = originalChildAssocRefs.get(versionedChildRef.getChildRef().getId()); assertNotNull(origChildAssocRef); assertEquals( origChildAssocRef.getChildRef(), versionedChildRef.getChildRef()); assertEquals( origChildAssocRef.isPrimary(), versionedChildRef.isPrimary()); assertEquals( origChildAssocRef.getNthSibling(), versionedChildRef.getNthSibling()); } } /** * Test getAssociationTargets */ public void testGetAssociationTargets() { // Create a new versionable node NodeRef versionableNode = createNewVersionableNode(); // Store the current details of the target associations List origAssocs = this.dbNodeService.getTargetAssocs( versionableNode, RegexQNamePattern.MATCH_ALL); // Create a new version Version version = createVersion(versionableNode, this.versionProperties); List assocs = this.versionStoreNodeService.getTargetAssocs( version.getFrozenStateNodeRef(), RegexQNamePattern.MATCH_ALL); assertNotNull(assocs); assertEquals(origAssocs.size(), assocs.size()); } /** * Test hasAspect */ public void testHasAspect() { // Create a new versionable node NodeRef versionableNode = createNewVersionableNode(); // Create a new version Version version = createVersion(versionableNode, this.versionProperties); boolean test1 = this.versionStoreNodeService.hasAspect( version.getFrozenStateNodeRef(), ApplicationModel.ASPECT_UIFACETS); assertFalse(test1); boolean test2 = this.versionStoreNodeService.hasAspect( version.getFrozenStateNodeRef(), ContentModel.ASPECT_VERSIONABLE); assertTrue(test2); } /** * Test getAspects */ public void testGetAspects() { // Create a new versionable node NodeRef versionableNode = createNewVersionableNode(); Set origAspects = this.dbNodeService.getAspects(versionableNode); // Create a new version Version version = createVersion(versionableNode, this.versionProperties); Set aspects = this.versionStoreNodeService.getAspects(version.getFrozenStateNodeRef()); assertEquals(origAspects.size(), aspects.size()); for (QName origAspect : origAspects) { assertTrue(origAspect+"",aspects.contains(origAspect)); } } /** * Test getParentAssocs */ public void testGetParentAssocs() { // Create a new versionable node NodeRef versionableNode = createNewVersionableNode(); // Create a new version Version version = createVersion(versionableNode, this.versionProperties); NodeRef nodeRef = version.getFrozenStateNodeRef(); List results = this.versionStoreNodeService.getParentAssocs(nodeRef); assertNotNull(results); assertEquals(1, results.size()); ChildAssociationRef childAssoc = results.get(0); assertEquals(nodeRef, childAssoc.getChildRef()); NodeRef versionStoreRoot = this.dbNodeService.getRootNode(this.versionService.getVersionStoreReference()); assertEquals(versionStoreRoot, childAssoc.getParentRef()); } /** * Test getPrimaryParent */ public void testGetPrimaryParent() { // Create a new versionable node NodeRef versionableNode = createNewVersionableNode(); // Create a new version Version version = createVersion(versionableNode, this.versionProperties); NodeRef nodeRef = version.getFrozenStateNodeRef(); ChildAssociationRef childAssoc = this.versionStoreNodeService.getPrimaryParent(nodeRef); assertNotNull(childAssoc); assertEquals(nodeRef, childAssoc.getChildRef()); NodeRef versionStoreRoot = this.dbNodeService.getRootNode(this.versionService.getVersionStoreReference()); assertEquals(versionStoreRoot, childAssoc.getParentRef()); } /** ================================================ * These test ensure that the following operations * are not supported as expected. */ /** * Test createNode */ public void testCreateNode() { try { this.versionStoreNodeService.createNode( dummyNodeRef, null, dummyQName, ContentModel.TYPE_CONTENT); fail("This operation is not supported."); } catch (UnsupportedOperationException exception) { if (exception.getMessage() != MSG_ERR) { fail("Unexpected exception raised during method excution: " + exception.getMessage()); } } } /** * Test addAspect */ public void testAddAspect() { try { this.versionStoreNodeService.addAspect( dummyNodeRef, TEST_ASPECT_QNAME, null); fail("This operation is not supported."); } catch (UnsupportedOperationException exception) { if (exception.getMessage() != MSG_ERR) { fail("Unexpected exception raised during method excution: " + exception.getMessage()); } } } /** * Test removeAspect */ public void testRemoveAspect() { try { this.versionStoreNodeService.removeAspect( dummyNodeRef, TEST_ASPECT_QNAME); fail("This operation is not supported."); } catch (UnsupportedOperationException exception) { if (exception.getMessage() != MSG_ERR) { fail("Unexpected exception raised during method excution: " + exception.getMessage()); } } } /** * Test delete node */ public void testDeleteNode() { try { this.versionStoreNodeService.deleteNode(this.dummyNodeRef); fail("This operation is not supported."); } catch (UnsupportedOperationException exception) { if (exception.getMessage() != MSG_ERR) { fail("Unexpected exception raised during method excution: " + exception.getMessage()); } } } /** * Test addChild */ public void testAddChild() { try { this.versionStoreNodeService.addChild( this.dummyNodeRef, this.dummyNodeRef, this.dummyQName, this.dummyQName); fail("This operation is not supported."); } catch (UnsupportedOperationException exception) { if (exception.getMessage() != MSG_ERR) { fail("Unexpected exception raised during method excution: " + exception.getMessage()); } } } /** * Test removeChild */ public void testRemoveChild() { try { this.versionStoreNodeService.removeChild( this.dummyNodeRef, this.dummyNodeRef); fail("This operation is not supported."); } catch (UnsupportedOperationException exception) { if (exception.getMessage() != MSG_ERR) { fail("Unexpected exception raised during method excution: " + exception.getMessage()); } } } /** * Test setProperties */ public void testSetProperties() { try { this.versionStoreNodeService.setProperties( this.dummyNodeRef, new HashMap()); fail("This operation is not supported."); } catch (UnsupportedOperationException exception) { if (exception.getMessage() != MSG_ERR) { fail("Unexpected exception raised during method excution: " + exception.getMessage()); } } } /** * Test setProperty */ public void testSetProperty() { try { this.versionStoreNodeService.setProperty( this.dummyNodeRef, this.dummyQName, "dummy"); fail("This operation is not supported."); } catch (UnsupportedOperationException exception) { if (exception.getMessage() != MSG_ERR) { fail("Unexpected exception raised during method excution: " + exception.getMessage()); } } } /** * Test createAssociation */ public void testCreateAssociation() { try { this.versionStoreNodeService.createAssociation( this.dummyNodeRef, this.dummyNodeRef, this.dummyQName); fail("This operation is not supported."); } catch (UnsupportedOperationException exception) { if (exception.getMessage() != MSG_ERR) { fail("Unexpected exception raised during method excution: " + exception.getMessage()); } } } /** * Test removeAssociation */ public void testRemoveAssociation() { try { this.versionStoreNodeService.removeAssociation( this.dummyNodeRef, this.dummyNodeRef, this.dummyQName); fail("This operation is not supported."); } catch (UnsupportedOperationException exception) { if (exception.getMessage() != MSG_ERR) { fail("Unexpected exception raised during method excution: " + exception.getMessage()); } } } /** * Test getAssociationSources */ public void testGetAssociationSources() { try { this.versionStoreNodeService.getSourceAssocs( this.dummyNodeRef, this.dummyQName); fail("This operation is not supported."); } catch (UnsupportedOperationException exception) { if (exception.getMessage() != MSG_ERR) { fail("Unexpected exception raised during method excution: " + exception.getMessage()); } } } /** * Test getPath */ public void testGetPath() { Path path = this.versionStoreNodeService.getPath(this.dummyNodeRef); } /** * Test getPaths */ public void testGetPaths() { List paths = this.versionStoreNodeService.getPaths(this.dummyNodeRef, false); } /** * Tests that we can store and retrieve unicode properties * and association names. * If there's something wrong with how we're setting up the * database or database connection WRT unicode, this is a * test that'll hopefully break in testing and alert us! */ public void testUnicodeNamesAndProperties() { // Get our cache objects List cachesToClear = new ArrayList(); cachesToClear.add( (TransactionalCache)this.applicationContext.getBean("propertyValueCache") ); cachesToClear.add( (TransactionalCache)this.applicationContext.getBean("node.nodesCache") ); cachesToClear.add( (TransactionalCache)this.applicationContext.getBean("node.propertiesCache") ); // First up, try with a simple English name+properties String engProp = "This is a property in English"; QName engQName = QName.createQName("NameSpace", "In English"); NodeRef engNode = nodeService.createNode( this.rootNodeRef, ContentModel.ASSOC_CONTAINS, engQName, ContentModel.TYPE_CONTENT ).getChildRef(); nodeService.setProperty(engNode, ContentModel.PROP_NAME, engProp); // Check they exist and are correct assertEquals(engProp, nodeService.getProperty(engNode, ContentModel.PROP_NAME)); assertEquals(1, nodeService.getChildAssocs(this.rootNodeRef, ContentModel.ASSOC_CONTAINS, engQName).size()); assertEquals(engNode, nodeService.getChildByName(rootNodeRef, ContentModel.ASSOC_CONTAINS, engProp)); // Now French String frProp = "C'est une propri\u00e9t\u00e9 en fran\u00e7ais"; // C'est une propriété en français QName frQName = QName.createQName("NameSpace", "En Fran\u00e7ais"); // En Français NodeRef frNode = nodeService.createNode( this.rootNodeRef, ContentModel.ASSOC_CONTAINS, frQName, ContentModel.TYPE_CONTENT ).getChildRef(); nodeService.setProperty(frNode, ContentModel.PROP_NAME, frProp); assertEquals(frProp, nodeService.getProperty(frNode, ContentModel.PROP_NAME)); assertEquals(1, nodeService.getChildAssocs(this.rootNodeRef, ContentModel.ASSOC_CONTAINS, frQName).size()); assertEquals(frNode, nodeService.getChildByName(rootNodeRef, ContentModel.ASSOC_CONTAINS, frProp)); // Zap the cache and re-check // (If the DB is broken but the cache works, then the above // tests could pass even in the face of a problem) for(TransactionalCache tc : cachesToClear) tc.clear(); assertEquals(frProp, nodeService.getProperty(frNode, ContentModel.PROP_NAME)); assertEquals(1, nodeService.getChildAssocs(this.rootNodeRef, ContentModel.ASSOC_CONTAINS, frQName).size()); assertEquals(frNode, nodeService.getChildByName(rootNodeRef, ContentModel.ASSOC_CONTAINS, frProp)); // Next Spanish String esProp = "Esta es una propiedad en Espa\u00f1ol"; // Esta es una propiedad en Español QName esQName = QName.createQName("NameSpace", "En Espa\u00f1ol"); // En Español NodeRef esNode = nodeService.createNode( this.rootNodeRef, ContentModel.ASSOC_CONTAINS, esQName, ContentModel.TYPE_CONTENT ).getChildRef(); nodeService.setProperty(esNode, ContentModel.PROP_NAME, esProp); assertEquals(esProp, nodeService.getProperty(esNode, ContentModel.PROP_NAME)); assertEquals(1, nodeService.getChildAssocs(this.rootNodeRef, ContentModel.ASSOC_CONTAINS, esQName).size()); assertEquals(esNode, nodeService.getChildByName(rootNodeRef, ContentModel.ASSOC_CONTAINS, esProp)); // Zap cache and re-test the Spanish for(TransactionalCache tc : cachesToClear) tc.clear(); assertEquals(esProp, nodeService.getProperty(esNode, ContentModel.PROP_NAME)); assertEquals(1, nodeService.getChildAssocs(this.rootNodeRef, ContentModel.ASSOC_CONTAINS, esQName).size()); assertEquals(esNode, nodeService.getChildByName(rootNodeRef, ContentModel.ASSOC_CONTAINS, esProp)); // Finally Japanese String jpProp = "\u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044\u3002"; // をクリック������。 QName jpQName = QName.createQName("NameSpace", "\u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u304f"); // をクリック��� NodeRef jpNode = nodeService.createNode( this.rootNodeRef, ContentModel.ASSOC_CONTAINS, jpQName, ContentModel.TYPE_CONTENT ).getChildRef(); nodeService.setProperty(jpNode, ContentModel.PROP_NAME, jpProp); assertEquals(jpProp, nodeService.getProperty(jpNode, ContentModel.PROP_NAME)); assertEquals(1, nodeService.getChildAssocs(this.rootNodeRef, ContentModel.ASSOC_CONTAINS, jpQName).size()); assertEquals(jpNode, nodeService.getChildByName(rootNodeRef, ContentModel.ASSOC_CONTAINS, jpProp)); // Zap the cache and check the Japanese for(TransactionalCache tc : cachesToClear) tc.clear(); assertEquals(jpProp, nodeService.getProperty(jpNode, ContentModel.PROP_NAME)); assertEquals(1, nodeService.getChildAssocs(this.rootNodeRef, ContentModel.ASSOC_CONTAINS, jpQName).size()); assertEquals(jpNode, nodeService.getChildByName(rootNodeRef, ContentModel.ASSOC_CONTAINS, jpProp)); } }