Moving to root below branch label

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2005 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2005-12-08 07:13:07 +00:00
commit e1e6508fec
1095 changed files with 230566 additions and 0 deletions

View File

@@ -0,0 +1,370 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.dictionary.DictionaryDAO;
import org.alfresco.repo.dictionary.M2Model;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.MutableAuthenticationDao;
import org.alfresco.repo.version.common.counter.VersionCounterDaoService;
import org.alfresco.repo.version.common.versionlabel.SerialVersionLabelPolicy;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.BaseSpringTest;
import org.alfresco.util.TestWithUserUtils;
public abstract class BaseVersionStoreTest extends BaseSpringTest
{
/*
* Services used by the tests
*/
protected NodeService dbNodeService;
protected VersionService versionService;
protected VersionCounterDaoService versionCounterDaoService;
protected ContentService contentService;
protected DictionaryDAO dictionaryDAO;
protected AuthenticationService authenticationService;
protected TransactionService transactionService;
protected MutableAuthenticationDao authenticationDAO;
/*
* Data used by tests
*/
protected StoreRef testStoreRef;
protected NodeRef rootNodeRef;
protected Map<String, Serializable> versionProperties;
protected HashMap<QName, Serializable> nodeProperties;
/**
* The most recent set of versionable nodes created by createVersionableNode
*/
protected HashMap<String, NodeRef> versionableNodes;
/*
* Proprety names and values
*/
protected static final String TEST_NAMESPACE = "http://www.alfresco.org/test/versionstorebasetest/1.0";
protected static final QName TEST_TYPE_QNAME = QName.createQName(TEST_NAMESPACE, "testtype");
protected static final QName TEST_ASPECT_QNAME = QName.createQName(TEST_NAMESPACE, "testaspect");
protected static final QName PROP_1 = QName.createQName(TEST_NAMESPACE, "prop1");
protected static final QName PROP_2 = QName.createQName(TEST_NAMESPACE, "prop2");
protected static final QName PROP_3 = QName.createQName(TEST_NAMESPACE, "prop3");
protected static final QName MULTI_PROP = QName.createQName(TEST_NAMESPACE, "multiProp");
protected static final String VERSION_PROP_1 = "versionProp1";
protected static final String VERSION_PROP_2 = "versionProp2";
protected static final String VERSION_PROP_3 = "versionProp3";
protected static final String VALUE_1 = "value1";
protected static final String VALUE_2 = "value2";
protected static final String VALUE_3 = "value3";
protected static final QName TEST_CHILD_ASSOC_1 = QName.createQName(TEST_NAMESPACE, "childassoc1");
protected static final QName TEST_CHILD_ASSOC_2 = QName.createQName(TEST_NAMESPACE, "childassoc2");
protected static final QName TEST_ASSOC = QName.createQName(TEST_NAMESPACE, "assoc1");
protected Collection<String> multiValue = null;
private AuthenticationComponent authenticationComponent;
protected static final String MULTI_VALUE_1 = "multi1";
protected static final String MULTI_VALUE_2 = "multi2";
/**
* Test content
*/
protected static final String TEST_CONTENT = "This is the versioned test content.";
/**
* Test user details
*/
private static final String PWD = "admin";
private static final String USER_NAME = "admin";
/**
* Sets the meta model dao
*
* @param dictionaryDAO the meta model dao
*/
public void setDictionaryDAO(DictionaryDAO dictionaryDAO)
{
this.dictionaryDAO = dictionaryDAO;
}
/**
* Called during the transaction setup
*/
protected void onSetUpInTransaction() throws Exception
{
// Set the multi value if required
if (this.multiValue == null)
{
this.multiValue = new ArrayList<String>();
this.multiValue.add(MULTI_VALUE_1);
this.multiValue.add(MULTI_VALUE_2);
}
// Get the services by name from the application context
this.dbNodeService = (NodeService)applicationContext.getBean("dbNodeService");
this.versionService = (VersionService)applicationContext.getBean("versionService");
this.versionCounterDaoService = (VersionCounterDaoService)applicationContext.getBean("versionCounterDaoService");
this.contentService = (ContentService)applicationContext.getBean("contentService");
this.authenticationService = (AuthenticationService)applicationContext.getBean("authenticationService");
this.authenticationComponent = (AuthenticationComponent)applicationContext.getBean("authenticationComponent");
this.transactionService = (TransactionService)this.applicationContext.getBean("transactionComponent");
this.authenticationDAO = (MutableAuthenticationDao) applicationContext.getBean("alfDaoImpl");
authenticationService.clearCurrentSecurityContext();
// Create the test model
createTestModel();
// Create a bag of properties for later use
this.versionProperties = new HashMap<String, Serializable>();
versionProperties.put(VERSION_PROP_1, VALUE_1);
versionProperties.put(VERSION_PROP_2, VALUE_2);
versionProperties.put(VERSION_PROP_3, VALUE_3);
// Create the node properties
this.nodeProperties = new HashMap<QName, Serializable>();
this.nodeProperties.put(PROP_1, VALUE_1);
this.nodeProperties.put(PROP_2, VALUE_2);
this.nodeProperties.put(PROP_3, VALUE_3);
this.nodeProperties.put(MULTI_PROP, (Serializable)multiValue);
this.nodeProperties.put(ContentModel.PROP_CONTENT, new ContentData(null, "text/plain", 0L, "UTF-8"));
// Create a workspace that contains the 'live' nodes
this.testStoreRef = this.dbNodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
// Get a reference to the root node
this.rootNodeRef = this.dbNodeService.getRootNode(this.testStoreRef);
// Create an authenticate the user
if(!authenticationDAO.userExists(USER_NAME))
{
authenticationService.createAuthentication(USER_NAME, PWD.toCharArray());
}
TestWithUserUtils.authenticateUser(USER_NAME, PWD, this.rootNodeRef, this.authenticationService);
}
/**
* Creates the test model used by the tests
*/
private void createTestModel()
{
InputStream is = getClass().getClassLoader().getResourceAsStream("org/alfresco/repo/version/VersionStoreBaseTest_model.xml");
M2Model model = M2Model.createModel(is);
dictionaryDAO.putModel(model);
}
/**
* Creates a new versionable node
*
* @return the node reference
*/
protected NodeRef createNewVersionableNode()
{
// Use this map to retrive the versionable nodes in later tests
this.versionableNodes = new HashMap<String, NodeRef>();
// Create node (this node has some content)
NodeRef nodeRef = this.dbNodeService.createNode(
rootNodeRef,
ContentModel.ASSOC_CHILDREN,
QName.createQName("{test}MyVersionableNode"),
TEST_TYPE_QNAME,
this.nodeProperties).getChildRef();
this.dbNodeService.addAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE, new HashMap<QName, Serializable>());
assertNotNull(nodeRef);
this.versionableNodes.put(nodeRef.getId(), nodeRef);
// Add the content to the node
ContentWriter contentWriter = this.contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
contentWriter.putContent(TEST_CONTENT);
// Add some children to the node
NodeRef child1 = this.dbNodeService.createNode(
nodeRef,
TEST_CHILD_ASSOC_1,
TEST_CHILD_ASSOC_1,
TEST_TYPE_QNAME,
this.nodeProperties).getChildRef();
this.dbNodeService.addAspect(child1, ContentModel.ASPECT_VERSIONABLE, new HashMap<QName, Serializable>());
assertNotNull(child1);
this.versionableNodes.put(child1.getId(), child1);
NodeRef child2 = this.dbNodeService.createNode(
nodeRef,
TEST_CHILD_ASSOC_2,
TEST_CHILD_ASSOC_2,
TEST_TYPE_QNAME,
this.nodeProperties).getChildRef();
this.dbNodeService.addAspect(child2, ContentModel.ASPECT_VERSIONABLE, new HashMap<QName, Serializable>());
assertNotNull(child2);
this.versionableNodes.put(child2.getId(), child2);
// Create a node that can be associated with the root node
NodeRef assocNode = this.dbNodeService.createNode(
rootNodeRef,
ContentModel.ASSOC_CHILDREN,
QName.createQName("{test}MyAssocNode"),
TEST_TYPE_QNAME,
this.nodeProperties).getChildRef();
assertNotNull(assocNode);
this.dbNodeService.createAssociation(nodeRef, assocNode, TEST_ASSOC);
return nodeRef;
}
/**
* Creates a new version, checking the properties of the version.
* <p>
* The default test propreties are assigned to the version.
*
* @param versionableNode the versionable node
* @return the created (and checked) new version
*/
protected Version createVersion(NodeRef versionableNode)
{
return createVersion(versionableNode, this.versionProperties);
}
/**
* Creates a new version, checking the properties of the version.
*
* @param versionableNode the versionable node
* @param versionProperties the version properties
* @return the created (and checked) new version
*/
protected Version createVersion(NodeRef versionableNode, Map<String, Serializable> versionProperties)
{
// Get the next version number
int nextVersion = peekNextVersionNumber();
String nextVersionLabel = peekNextVersionLabel(versionableNode, nextVersion, versionProperties);
// Snap-shot the date-time
long beforeVersionTime = System.currentTimeMillis();
// Now lets create a new version for this node
Version newVersion = versionService.createVersion(versionableNode, this.versionProperties);
checkNewVersion(beforeVersionTime, nextVersion, nextVersionLabel, newVersion, versionableNode);
// Return the new version
return newVersion;
}
/**
* Gets the next version label
*/
protected String peekNextVersionLabel(NodeRef nodeRef, int versionNumber, Map<String, Serializable> versionProperties)
{
Version version = this.versionService.getCurrentVersion(nodeRef);
SerialVersionLabelPolicy policy = new SerialVersionLabelPolicy();
return policy.calculateVersionLabel(ContentModel.TYPE_CMOBJECT, version, versionNumber, versionProperties);
}
/**
* Checkd the validity of a new version
*
* @param beforeVersionTime the time snap shot before the version was created
* @param expectedVersionNumber the expected version number
* @param newVersion the new version
* @param versionableNode the versioned node
*/
protected void checkNewVersion(long beforeVersionTime, int expectedVersionNumber, String expectedVersionLabel, Version newVersion, NodeRef versionableNode)
{
assertNotNull(newVersion);
// Check the version label and version number
assertEquals(
"The expected version number was not used.",
Integer.toString(expectedVersionNumber),
newVersion.getVersionProperty(VersionModel.PROP_VERSION_NUMBER).toString());
assertEquals(
"The expected version label was not used.",
expectedVersionLabel,
newVersion.getVersionLabel());
// Check the created date
long afterVersionTime = System.currentTimeMillis();
long createdDate = newVersion.getCreatedDate().getTime();
if (createdDate < beforeVersionTime || createdDate > afterVersionTime)
{
fail("The created date of the version is incorrect.");
}
// Check the creator
assertEquals(USER_NAME, newVersion.getCreator());
// Check the properties of the verison
Map<String, Serializable> props = newVersion.getVersionProperties();
assertNotNull("The version properties collection should not be null.", props);
// TODO sort this out - need to check for the reserved properties too
//assertEquals(versionProperties.size(), props.size());
for (String key : versionProperties.keySet())
{
assertEquals(
versionProperties.get(key),
newVersion.getVersionProperty(key));
}
// Check that the node reference is correct
NodeRef nodeRef = newVersion.getFrozenStateNodeRef();
assertNotNull(nodeRef);
assertEquals(
VersionModel.STORE_ID,
nodeRef.getStoreRef().getIdentifier());
assertEquals(
VersionModel.STORE_PROTOCOL,
nodeRef.getStoreRef().getProtocol());
assertNotNull(nodeRef.getId());
// TODO: How do we check the frozen attributes ??
// Check the node ref for the current version
String currentVersionLabel = (String)this.dbNodeService.getProperty(
versionableNode,
ContentModel.PROP_VERSION_LABEL);
assertEquals(newVersion.getVersionLabel(), currentVersionLabel);
}
/**
* Returns the next version number without affecting the version counter.
*
* @return the next version number to be allocated
*/
protected int peekNextVersionNumber()
{
StoreRef lwVersionStoreRef = this.versionService.getVersionStoreReference();
return this.versionCounterDaoService.currentVersionNumber(lwVersionStoreRef) + 1;
}
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.Version;
/**
* Tests for retrieving frozen content from a verioned node
*
* @author Roy Wetherall
*/
public class ContentServiceImplTest extends BaseVersionStoreTest
{
/**
* Test content data
*/
private final static String UPDATED_CONTENT = "This content has been updated with a new value.";
/**
* The version content store
*/
private ContentService contentService;
/**
* Called during the transaction setup
*/
protected void onSetUpInTransaction() throws Exception
{
super.onSetUpInTransaction();
// Get the instance of the required content service
this.contentService = (ContentService)this.applicationContext.getBean("contentService");
}
/**
* Test getReader
*/
public void testGetReader()
{
// Create a new versionable node
NodeRef versionableNode = createNewVersionableNode();
// Create a new version
Version version = createVersion(versionableNode, this.versionProperties);
NodeRef versionNodeRef = version.getFrozenStateNodeRef();
// Get the content reader for the frozen node
ContentReader contentReader = this.contentService.getReader(versionNodeRef, ContentModel.PROP_CONTENT);
assertNotNull(contentReader);
assertEquals(TEST_CONTENT, contentReader.getContentString());
// Now update the content and verison again
ContentWriter contentWriter = this.contentService.getWriter(versionableNode, ContentModel.PROP_CONTENT, true);
assertNotNull(contentWriter);
contentWriter.putContent(UPDATED_CONTENT);
Version version2 = createVersion(versionableNode, this.versionProperties);
NodeRef version2NodeRef = version2.getFrozenStateNodeRef();
// Get the content reader for the new verisoned content
ContentReader contentReader2 = this.contentService.getReader(version2NodeRef, ContentModel.PROP_CONTENT);
assertNotNull(contentReader2);
assertEquals(UPDATED_CONTENT, contentReader2.getContentString());
}
/**
* Test getWriter
*/
public void testGetWriter()
{
// Create a new versionable node
NodeRef versionableNode = createNewVersionableNode();
// Create a new version
Version version = createVersion(versionableNode, this.versionProperties);
// Get writer is not supported by the version content service
try
{
ContentWriter contentWriter = this.contentService.getWriter(
version.getFrozenStateNodeRef(),
ContentModel.PROP_CONTENT,
true);
contentWriter.putContent("bobbins");
fail("This operation is not supported.");
}
catch (Exception exception)
{
// An exception should be raised
}
}
}

View File

@@ -0,0 +1,562 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.InvalidAspectException;
import org.alfresco.service.cmr.repository.AssociationExistsException;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.InvalidChildAssociationRefException;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
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.repository.StoreRef;
import org.alfresco.service.cmr.repository.NodeRef.Status;
import org.alfresco.service.cmr.search.QueryParameterDefinition;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.QNamePattern;
import org.alfresco.service.namespace.RegexQNamePattern;
/**
* The light weight version store node service implementation.
*
* @author Roy Wetherall
*/
public class NodeServiceImpl implements NodeService, VersionModel
{
/**
* Error messages
*/
private final static String MSG_UNSUPPORTED =
"This operation is not supported by a version store implementation of the node service.";
/**
* The name of the spoofed root association
*/
private static final QName rootAssocName = QName.createQName(VersionModel.NAMESPACE_URI, "versionedState");
/**
* The db node service, used as the version store implementation
*/
protected NodeService dbNodeService;
/**
* The repository searcher
*/
@SuppressWarnings("unused")
private SearchService searcher;
/**
* The dictionary service
*/
protected DictionaryService dicitionaryService;
/**
* Sets the db node service, used as the version store implementation
*
* @param nodeService the node service
*/
public void setDbNodeService(NodeService nodeService)
{
this.dbNodeService = nodeService;
}
/**
* Sets the searcher
*
* @param searcher the searcher
*/
public void setSearcher(SearchService searcher)
{
this.searcher = searcher;
}
/**
* Sets the dictionary service
*
* @param dictionaryService the dictionary service
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dicitionaryService = dictionaryService;
}
/**
* Delegates to the <code>NodeService</code> used as the version store implementation
*/
public List<StoreRef> getStores()
{
return dbNodeService.getStores();
}
/**
* Delegates to the <code>NodeService</code> used as the version store implementation
*/
public StoreRef createStore(String protocol, String identifier)
{
return dbNodeService.createStore(protocol, identifier);
}
/**
* Delegates to the <code>NodeService</code> used as the version store implementation
*/
public boolean exists(StoreRef storeRef)
{
return dbNodeService.exists(storeRef);
}
/**
* Delegates to the <code>NodeService</code> used as the version store implementation
*/
public boolean exists(NodeRef nodeRef)
{
return dbNodeService.exists(convertNodeRef(nodeRef));
}
/**
* Delegates to the <code>NodeService</code> used as the version store implementation
*/
public Status getNodeStatus(NodeRef nodeRef)
{
return dbNodeService.getNodeStatus(nodeRef);
}
/**
* Convert the incomming node ref (with the version store protocol specified)
* to the internal representation with the workspace protocol.
*
* @param nodeRef the incomming verison protocol node reference
* @return the internal version node reference
*/
private NodeRef convertNodeRef(NodeRef nodeRef)
{
return new NodeRef(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, STORE_ID), nodeRef.getId());
}
/**
* Delegates to the <code>NodeService</code> used as the version store implementation
*/
public NodeRef getRootNode(StoreRef storeRef)
{
return dbNodeService.getRootNode(storeRef);
}
/**
* @throws UnsupportedOperationException always
*/
public ChildAssociationRef createNode(
NodeRef parentRef,
QName assocTypeQName,
QName assocQName,
QName nodeTypeQName) throws InvalidNodeRefException
{
// This operation is not supported for a verion store
throw new UnsupportedOperationException(MSG_UNSUPPORTED);
}
/**
* @throws UnsupportedOperationException always
*/
public ChildAssociationRef createNode(
NodeRef parentRef,
QName assocTypeQName,
QName assocQName,
QName nodeTypeQName,
Map<QName, Serializable> properties) throws InvalidNodeRefException
{
// This operation is not supported for a verion store
throw new UnsupportedOperationException(MSG_UNSUPPORTED);
}
/**
* @throws UnsupportedOperationException always
*/
public void deleteNode(NodeRef nodeRef) throws InvalidNodeRefException
{
// This operation is not supported for a verion store
throw new UnsupportedOperationException(MSG_UNSUPPORTED);
}
/**
* @throws UnsupportedOperationException always
*/
public ChildAssociationRef addChild(NodeRef parentRef,
NodeRef childRef,
QName assocTypeQName,
QName qname) throws InvalidNodeRefException
{
// This operation is not supported for a verion store
throw new UnsupportedOperationException(MSG_UNSUPPORTED);
}
/**
* @throws UnsupportedOperationException always
*/
public void removeChild(NodeRef parentRef, NodeRef childRef) throws InvalidNodeRefException
{
// This operation is not supported for a verion store
throw new UnsupportedOperationException(MSG_UNSUPPORTED);
}
/**
* @throws UnsupportedOperationException always
*/
public ChildAssociationRef moveNode(NodeRef nodeToMoveRef, NodeRef newParentRef, QName assocTypeQName, QName assocQName) throws InvalidNodeRefException
{
throw new UnsupportedOperationException(MSG_UNSUPPORTED);
}
/**
* @throws UnsupportedOperationException always
*/
public void setChildAssociationIndex(ChildAssociationRef childAssocRef, int index) throws InvalidChildAssociationRefException
{
throw new UnsupportedOperationException(MSG_UNSUPPORTED);
}
/**
* Type translation for version store
*/
public QName getType(NodeRef nodeRef) throws InvalidNodeRefException
{
return (QName)this.dbNodeService.getProperty(convertNodeRef(nodeRef), PROP_QNAME_FROZEN_NODE_TYPE);
}
/**
* @see org.alfresco.service.cmr.repository.NodeService#setType(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName)
*/
public void setType(NodeRef nodeRef, QName typeQName) throws InvalidNodeRefException
{
// This operation is not supported for a version store
throw new UnsupportedOperationException(MSG_UNSUPPORTED);
}
/**
* @throws UnsupportedOperationException always
*/
public void addAspect(NodeRef nodeRef, QName aspectRef, Map<QName, Serializable> aspectProperties) throws InvalidNodeRefException, InvalidAspectException
{
// This operation is not supported for a verion store
throw new UnsupportedOperationException(MSG_UNSUPPORTED);
}
/**
* Translation for version store
*/
public boolean hasAspect(NodeRef nodeRef, QName aspectRef) throws InvalidNodeRefException, InvalidAspectException
{
return getAspects(nodeRef).contains(aspectRef);
}
/**
* @throws UnsupportedOperationException always
*/
public void removeAspect(NodeRef nodeRef, QName aspectRef) throws InvalidNodeRefException, InvalidAspectException
{
// This operation is not supported for a verion store
throw new UnsupportedOperationException(MSG_UNSUPPORTED);
}
/**
* Translation for version store
*/
public Set<QName> getAspects(NodeRef nodeRef) throws InvalidNodeRefException
{
return new HashSet<QName>(
(ArrayList<QName>)this.dbNodeService.getProperty(convertNodeRef(nodeRef), PROP_QNAME_FROZEN_ASPECTS));
}
/**
* Property translation for version store
*/
public Map<QName, Serializable> getProperties(NodeRef nodeRef) throws InvalidNodeRefException
{
Map<QName, Serializable> result = new HashMap<QName, Serializable>();
// TODO should be doing this using a path query ..
Collection<ChildAssociationRef> children = this.dbNodeService.getChildAssocs(convertNodeRef(nodeRef));
for (ChildAssociationRef child : children)
{
if (child.getQName().equals(CHILD_QNAME_VERSIONED_ATTRIBUTES))
{
NodeRef versionedAttribute = child.getChildRef();
// Get the QName and the value
Serializable value = null;
QName qName = (QName)this.dbNodeService.getProperty(versionedAttribute, PROP_QNAME_QNAME);
Boolean isMultiValue = (Boolean)this.dbNodeService.getProperty(versionedAttribute, PROP_QNAME_IS_MULTI_VALUE);
if (isMultiValue.booleanValue() == false)
{
value = this.dbNodeService.getProperty(versionedAttribute, PROP_QNAME_VALUE);
}
else
{
value = this.dbNodeService.getProperty(versionedAttribute, PROP_QNAME_MULTI_VALUE);
}
result.put(qName, value);
}
}
return result;
}
/**
* Property translation for version store
*/
public Serializable getProperty(NodeRef nodeRef, QName qname) throws InvalidNodeRefException
{
// TODO should be doing this with a search ...
Map<QName, Serializable> properties = getProperties(convertNodeRef(nodeRef));
return properties.get(qname);
}
/**
* @throws UnsupportedOperationException always
*/
public void setProperties(NodeRef nodeRef, Map<QName, Serializable> properties) throws InvalidNodeRefException
{
// This operation is not supported for a verion store
throw new UnsupportedOperationException(MSG_UNSUPPORTED);
}
/**
* @throws UnsupportedOperationException always
*/
public void setProperty(NodeRef nodeRef, QName qame, Serializable value) throws InvalidNodeRefException
{
// This operation is not supported for a verion store
throw new UnsupportedOperationException(MSG_UNSUPPORTED);
}
/**
* The node will appear to be attached to the root of the version store
*
* @see NodeService#getParentAssocs(NodeRef)
*/
public List<ChildAssociationRef> getParentAssocs(NodeRef nodeRef)
{
return getParentAssocs(nodeRef, RegexQNamePattern.MATCH_ALL, RegexQNamePattern.MATCH_ALL);
}
/**
* The node will apprear to be attached to the root of the version store
*
* @see NodeService#getParentAssocs(NodeRef, QNamePattern, QNamePattern)
*/
public List<ChildAssociationRef> getParentAssocs(NodeRef nodeRef, QNamePattern typeQNamePattern, QNamePattern qnamePattern)
{
List<ChildAssociationRef> result = new ArrayList<ChildAssociationRef>();
if (qnamePattern.isMatch(rootAssocName) == true)
{
result.add(new ChildAssociationRef(
ContentModel.ASSOC_CHILDREN,
dbNodeService.getRootNode(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, STORE_ID)),
rootAssocName,
nodeRef));
}
return result;
}
/**
* @see RegexQNamePattern#MATCH_ALL
* @see #getChildAssocs(NodeRef, QNamePattern, QNamePattern)
*/
public List<ChildAssociationRef> getChildAssocs(NodeRef nodeRef) throws InvalidNodeRefException
{
return getChildAssocs(convertNodeRef(nodeRef), RegexQNamePattern.MATCH_ALL, RegexQNamePattern.MATCH_ALL);
}
/**
* Performs conversion from version store properties to <i>real</i> associations
*/
public List<ChildAssociationRef> getChildAssocs(NodeRef nodeRef, QNamePattern typeQNamePattern, QNamePattern qnamePattern) throws InvalidNodeRefException
{
// Get the child assocs from the version store
List<ChildAssociationRef> childAssocRefs = this.dbNodeService.getChildAssocs(
convertNodeRef(nodeRef),
RegexQNamePattern.MATCH_ALL, CHILD_QNAME_VERSIONED_CHILD_ASSOCS);
List<ChildAssociationRef> result = new ArrayList<ChildAssociationRef>(childAssocRefs.size());
for (ChildAssociationRef childAssocRef : childAssocRefs)
{
// Get the child reference
NodeRef childRef = childAssocRef.getChildRef();
NodeRef referencedNode = (NodeRef)this.dbNodeService.getProperty(childRef, ContentModel.PROP_REFERENCE);
// get the qualified name of the frozen child association and filter out unwanted names
QName qName = (QName)this.dbNodeService.getProperty(childRef, PROP_QNAME_ASSOC_QNAME);
if (qnamePattern.isMatch(qName) == true)
{
// Retrieve the isPrimary and nthSibling values of the forzen child association
QName assocType = (QName)this.dbNodeService.getProperty(childRef, PROP_QNAME_ASSOC_TYPE_QNAME);
boolean isPrimary = ((Boolean)this.dbNodeService.getProperty(childRef, PROP_QNAME_IS_PRIMARY)).booleanValue();
int nthSibling = ((Integer)this.dbNodeService.getProperty(childRef, PROP_QNAME_NTH_SIBLING)).intValue();
// Build a child assoc ref to add to the returned list
ChildAssociationRef newChildAssocRef = new ChildAssociationRef(
assocType,
nodeRef,
qName,
referencedNode,
isPrimary,
nthSibling);
result.add(newChildAssocRef);
}
}
// sort the results so that the order appears to be exactly as it was originally
Collections.sort(result);
return result;
}
/**
* Simulates the node begin attached ot the root node of the version store.
*/
public ChildAssociationRef getPrimaryParent(NodeRef nodeRef) throws InvalidNodeRefException
{
return new ChildAssociationRef(
ContentModel.ASSOC_CHILDREN,
dbNodeService.getRootNode(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, STORE_ID)),
rootAssocName,
nodeRef);
}
/**
* @throws UnsupportedOperationException always
*/
public AssociationRef createAssociation(NodeRef sourceRef, NodeRef targetRef, QName assocTypeQName)
throws InvalidNodeRefException, AssociationExistsException
{
// This operation is not supported for a verion store
throw new UnsupportedOperationException(MSG_UNSUPPORTED);
}
/**
* @throws UnsupportedOperationException always
*/
public void removeAssociation(NodeRef sourceRef, NodeRef targetRef, QName assocTypeQName)
{
// This operation is not supported for a verion store
throw new UnsupportedOperationException(MSG_UNSUPPORTED);
}
/**
* @throws UnsupportedOperationException always
*/
public List<AssociationRef> getTargetAssocs(NodeRef sourceRef, QNamePattern qnamePattern)
{
// Get the child assocs from the version store
List<ChildAssociationRef> childAssocRefs = this.dbNodeService.getChildAssocs(
convertNodeRef(sourceRef),
RegexQNamePattern.MATCH_ALL, CHILD_QNAME_VERSIONED_ASSOCS);
List<AssociationRef> result = new ArrayList<AssociationRef>(childAssocRefs.size());
for (ChildAssociationRef childAssocRef : childAssocRefs)
{
// Get the assoc reference
NodeRef childRef = childAssocRef.getChildRef();
NodeRef referencedNode = (NodeRef)this.dbNodeService.getProperty(childRef, ContentModel.PROP_REFERENCE);
// get the qualified type name of the frozen child association and filter out unwanted names
QName qName = (QName)this.dbNodeService.getProperty(childRef, PROP_QNAME_ASSOC_TYPE_QNAME);
if (qnamePattern.isMatch(qName) == true)
{
AssociationRef newAssocRef = new AssociationRef(sourceRef, qName, referencedNode);
result.add(newAssocRef);
}
}
return result;
}
/**
* @throws UnsupportedOperationException always
*/
public List<AssociationRef> getSourceAssocs(NodeRef sourceRef, QNamePattern qnamePattern)
{
// This operation is not supported for a verion store
throw new UnsupportedOperationException(MSG_UNSUPPORTED);
}
/**
* @throws UnsupportedOperationException always
*/
public Path getPath(NodeRef nodeRef) throws InvalidNodeRefException
{
ChildAssociationRef childAssocRef = getPrimaryParent(nodeRef);
Path path = new Path();
path.append(new Path.ChildAssocElement(childAssocRef));
return path;
}
/**
* @throws UnsupportedOperationException always
*/
public List<Path> getPaths(NodeRef nodeRef, boolean primaryOnly) throws InvalidNodeRefException
{
List<Path> paths = new ArrayList<Path>(1);
paths.add(getPath(nodeRef));
return paths;
}
public List<NodeRef> selectNodes(NodeRef contextNode, String XPath, QueryParameterDefinition[] parameters, NamespacePrefixResolver namespacePrefixResolver, boolean followAllParentLinks)
{
// TODO Auto-generated method stub
throw new UnsupportedOperationException(MSG_UNSUPPORTED);
}
public List<Serializable> selectProperties(NodeRef contextNode, String XPath, QueryParameterDefinition[] parameters, NamespacePrefixResolver namespacePrefixResolver, boolean followAllParentLinks)
{
// TODO Auto-generated method stub
throw new UnsupportedOperationException(MSG_UNSUPPORTED);
}
public boolean contains(NodeRef nodeRef, QName property, String sqlLikePattern)
{
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
public boolean like(NodeRef nodeRef, QName property, String sqlLikePattern, boolean includeFTS)
{
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,568 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel;
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);
/**
* Light weight version store node service
*/
protected NodeService lightWeightVersionStoreNodeService = 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.lightWeightVersionStoreNodeService = (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.lightWeightVersionStoreNodeService.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<QName, Serializable> origProps = this.dbNodeService.getProperties(versionableNode);
// Create a new version
Version version = createVersion(versionableNode, this.versionProperties);
// Get the properties of the versioned state
Map<QName, Serializable> versionedProperties = this.lightWeightVersionStoreNodeService.getProperties(version.getFrozenStateNodeRef());
//assertEquals(origProps.size(), versionedProperties.size());
for (QName key : origProps.keySet())
{
assertTrue(versionedProperties.containsKey(key));
assertEquals(origProps.get(key), versionedProperties.get(key));
}
// 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.lightWeightVersionStoreNodeService.getProperty(
version.getFrozenStateNodeRef(),
PROP_1);
assertEquals(VALUE_1, value1);
// Check the multi values property specifically
Collection<String> multiValue = (Collection<String>)this.lightWeightVersionStoreNodeService.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.isDebugEnabled())
{
// Let's have a look at the version store ..
System.out.println(NodeStoreInspector.dumpNodeStore(
this.dbNodeService,
this.versionService.getVersionStoreReference()) + "\n\n");
logger.debug("");
}
// Create a new versionable node
NodeRef versionableNode = createNewVersionableNode();
Collection<ChildAssociationRef> origionalChildren = this.dbNodeService.getChildAssocs(versionableNode);
assertNotNull(origionalChildren);
// Store the origional children in a map for easy navigation later
HashMap<String, ChildAssociationRef> origionalChildAssocRefs = new HashMap<String, ChildAssociationRef>();
for (ChildAssociationRef ref : origionalChildren)
{
origionalChildAssocRefs.put(ref.getChildRef().getId(), ref);
}
// Create a new version
Version version = createVersion(versionableNode, this.versionProperties);
if (logger.isDebugEnabled())
{
// Let's have a look at the version store ..
System.out.println(NodeStoreInspector.dumpNodeStore(
this.dbNodeService,
this.versionService.getVersionStoreReference()));
}
// Get the children of the versioned node
Collection<ChildAssociationRef> versionedChildren = this.lightWeightVersionStoreNodeService.getChildAssocs(version.getFrozenStateNodeRef());
assertNotNull(versionedChildren);
assertEquals(origionalChildren.size(), versionedChildren.size());
for (ChildAssociationRef versionedChildRef : versionedChildren)
{
ChildAssociationRef origChildAssocRef = origionalChildAssocRefs.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<AssociationRef> origAssocs = this.dbNodeService.getTargetAssocs(
versionableNode,
RegexQNamePattern.MATCH_ALL);
// Create a new version
Version version = createVersion(versionableNode, this.versionProperties);
List<AssociationRef> assocs = this.lightWeightVersionStoreNodeService.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.lightWeightVersionStoreNodeService.hasAspect(
version.getFrozenStateNodeRef(),
ContentModel.ASPECT_UIFACETS);
assertFalse(test1);
boolean test2 = this.lightWeightVersionStoreNodeService.hasAspect(
version.getFrozenStateNodeRef(),
ContentModel.ASPECT_VERSIONABLE);
assertTrue(test2);
}
/**
* Test getAspects
*/
public void testGetAspects()
{
// Create a new versionable node
NodeRef versionableNode = createNewVersionableNode();
Set<QName> origAspects = this.dbNodeService.getAspects(versionableNode);
// Create a new version
Version version = createVersion(versionableNode, this.versionProperties);
Set<QName> aspects = this.lightWeightVersionStoreNodeService.getAspects(version.getFrozenStateNodeRef());
assertEquals(origAspects.size(), aspects.size());
// TODO check that the set's contain the same items
}
/**
* 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<ChildAssociationRef> results = this.lightWeightVersionStoreNodeService.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.lightWeightVersionStoreNodeService.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.lightWeightVersionStoreNodeService.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.lightWeightVersionStoreNodeService.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.lightWeightVersionStoreNodeService.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.lightWeightVersionStoreNodeService.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.lightWeightVersionStoreNodeService.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.lightWeightVersionStoreNodeService.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.lightWeightVersionStoreNodeService.setProperties(
this.dummyNodeRef,
new HashMap<QName, Serializable>());
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.lightWeightVersionStoreNodeService.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.lightWeightVersionStoreNodeService.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.lightWeightVersionStoreNodeService.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.lightWeightVersionStoreNodeService.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.lightWeightVersionStoreNodeService.getPath(this.dummyNodeRef);
}
/**
* Test getPaths
*/
public void testGetPaths()
{
List<Path> paths = this.lightWeightVersionStoreNodeService.getPaths(this.dummyNodeRef, false);
}
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version;
import javax.transaction.UserTransaction;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.transaction.TransactionService;
/**
* Bootstrap Version Store
*
* @author David Caruana
*/
public class VersionBootstrap
{
private TransactionService transactionService;
private NodeService nodeService;
private AuthenticationComponent authenticationComponent;
private PermissionService permissionService;
/**
* Sets the Transaction Service
*
* @param userTransaction the user transaction
*/
public void setTransactionService(TransactionService transactionService)
{
this.transactionService = transactionService;
}
/**
* Sets the Node Service
*
* @param nodeService the node service
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setAuthenticationComponent(AuthenticationComponent authenticationComponent)
{
this.authenticationComponent = authenticationComponent;
}
public void setPermissionService(PermissionService permissionService)
{
this.permissionService = permissionService;
}
/**
* Bootstrap the Version Store
*/
public void bootstrap()
{
UserTransaction userTransaction = transactionService.getUserTransaction();
authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName());
try
{
userTransaction.begin();
// Ensure that the version store has been created
if (this.nodeService.exists(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, VersionModel.STORE_ID)) == true)
{
userTransaction.rollback();
}
else
{
StoreRef vStore = this.nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, VersionModel.STORE_ID);
// TODO: For now there are no permissions on version access
permissionService.setPermission(nodeService.getRootNode(vStore), permissionService.getAllAuthorities(), permissionService.getAllPermission(), true);
userTransaction.commit();
}
}
catch(Throwable e)
{
// rollback the transaction
try { if (userTransaction != null) {userTransaction.rollback();} } catch (Exception ex) {}
try {authenticationComponent.clearCurrentSecurityContext(); } catch (Exception ex) {}
throw new AlfrescoRuntimeException("Bootstrap failed", e);
}
finally
{
authenticationComponent.clearCurrentSecurityContext();
}
}
}

View File

@@ -0,0 +1,161 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.namespace.QName;
/**
* interface conating the constants used by the light weight
* version store implementation
*
* @author Roy Wetherall
*/
public interface VersionModel
{
/**
* Namespace
*/
public static final String NAMESPACE_URI = "http://www.alfresco.org/model/versionstore/1.0";
/**
* The store protocol
*/
public static final String STORE_PROTOCOL = VersionService.VERSION_STORE_PROTOCOL;
/**
* The store id
*/
public static final String STORE_ID = "lightWeightVersionStore";
public static final String PROP_VERSION_LABEL = "versionLabel";
public static final String PROP_CREATED_DATE = ContentModel.PROP_CREATED.getLocalName();
public static final String PROP_CREATOR = ContentModel.PROP_CREATOR.getLocalName();
public static final String PROP_VERSION_TYPE = "versionType";
public static final String PROP_VERSION_NUMBER = "versionNumber";
public static final String PROP_FROZEN_NODE_ID = "frozenNodeId";
public static final String PROP_FROZEN_NODE_TYPE = "frozenNodeType";
public static final String PROP_FROZEN_NODE_STORE_PROTOCOL = "frozenNodeStoreProtocol";
public static final String PROP_FROZEN_NODE_STORE_ID = "frozenNodeStoreId";
public static final String PROP_FROZEN_ASPECTS = "frozenAspects";
/**
* Version history type
*/
public static final String TYPE_VERSION_HISTORY = "versionHistory";
public static final QName TYPE_QNAME_VERSION_HISTORY = QName.createQName(NAMESPACE_URI, TYPE_VERSION_HISTORY);
/**
* Version history properties and associations
*/
public static final String PROP_VERSIONED_NODE_ID = "versionedNodeId";
public static final QName PROP_QNAME_VERSIONED_NODE_ID = QName.createQName(NAMESPACE_URI, PROP_VERSIONED_NODE_ID);
public static final QName ASSOC_ROOT_VERSION = QName.createQName(NAMESPACE_URI, "rootVersion");
/**
* Verison type
*/
public static final String TYPE_VERSION = "version";
public static final QName TYPE_QNAME_VERSION = QName.createQName(NAMESPACE_URI, TYPE_VERSION);
/**
* Version type properties and associations
*/
public static final QName PROP_QNAME_VERSION_LABEL = QName.createQName(NAMESPACE_URI, PROP_VERSION_LABEL);
public static final QName PROP_QNAME_VERSION_NUMBER = QName.createQName(NAMESPACE_URI, PROP_VERSION_NUMBER);
public static final QName PROP_QNAME_FROZEN_NODE_ID = QName.createQName(NAMESPACE_URI, PROP_FROZEN_NODE_ID);
public static final QName PROP_QNAME_FROZEN_NODE_TYPE = QName.createQName(NAMESPACE_URI, PROP_FROZEN_NODE_TYPE);
public static final QName PROP_QNAME_FROZEN_NODE_STORE_PROTOCOL = QName.createQName(NAMESPACE_URI, PROP_FROZEN_NODE_STORE_PROTOCOL);
public static final QName PROP_QNAME_FROZEN_NODE_STORE_ID = QName.createQName(NAMESPACE_URI, PROP_FROZEN_NODE_STORE_ID);
public static final QName PROP_QNAME_FROZEN_ASPECTS = QName.createQName(NAMESPACE_URI, PROP_FROZEN_ASPECTS);
public static final QName ASSOC_SUCCESSOR = QName.createQName(NAMESPACE_URI, "successor");
/**
* Version Meta Data Value type
*/
public static final String TYPE_VERSION_META_DATA_VALUE = "versionMetaDataValue";
public static final QName TYPE_QNAME_VERSION_META_DATA_VALUE = QName.createQName(NAMESPACE_URI, TYPE_VERSION_META_DATA_VALUE);
/**
* Version Meta Data Value attributes
*/
public static final String PROP_META_DATA_NAME = "metaDataName";
public static final QName PROP_QNAME_META_DATA_NAME = QName.createQName(NAMESPACE_URI, PROP_META_DATA_NAME);
public static final String PROP_META_DATA_VALUE = "metaDataValue";
public static final QName PROP_QNAME_META_DATA_VALUE = QName.createQName(NAMESPACE_URI, PROP_META_DATA_VALUE);
/**
* Versioned attribute type
*/
public static final String TYPE_VERSIONED_PROPERTY = "versionedProperty";
public static final QName TYPE_QNAME_VERSIONED_PROPERTY = QName.createQName(NAMESPACE_URI, TYPE_VERSIONED_PROPERTY);
/**
* Versioned attribute properties
*/
public static final String PROP_QNAME = "qname";
public static final String PROP_VALUE = "value";
public static final String PROP_MULTI_VALUE = "multiValue";
public static final String PROP_IS_MULTI_VALUE = "isMultiValue";
public static final QName PROP_QNAME_QNAME = QName.createQName(NAMESPACE_URI, PROP_QNAME);
public static final QName PROP_QNAME_VALUE = QName.createQName(NAMESPACE_URI, PROP_VALUE);
public static final QName PROP_QNAME_MULTI_VALUE = QName.createQName(NAMESPACE_URI, PROP_MULTI_VALUE);
public static final QName PROP_QNAME_IS_MULTI_VALUE = QName.createQName(NAMESPACE_URI, PROP_IS_MULTI_VALUE);
/**
* Versioned child assoc type
*/
public static final String TYPE_VERSIONED_CHILD_ASSOC = "versionedChildAssoc";
public static final QName TYPE_QNAME_VERSIONED_CHILD_ASSOC = QName.createQName(NAMESPACE_URI, TYPE_VERSIONED_CHILD_ASSOC);
/**
* Versioned child assoc properties
*/
public static final String PROP_ASSOC_QNAME = "assocQName";
public static final String PROP_ASSOC_TYPE_QNAME = "assocTypeQName";
public static final String PROP_IS_PRIMARY = "isPrimary";
public static final String PROP_NTH_SIBLING = "nthSibling";
public static final QName PROP_QNAME_ASSOC_QNAME = QName.createQName(NAMESPACE_URI, PROP_ASSOC_QNAME);
public static final QName PROP_QNAME_ASSOC_TYPE_QNAME = QName.createQName(NAMESPACE_URI, PROP_ASSOC_TYPE_QNAME);
public static final QName PROP_QNAME_IS_PRIMARY = QName.createQName(NAMESPACE_URI, PROP_IS_PRIMARY);
public static final QName PROP_QNAME_NTH_SIBLING = QName.createQName(NAMESPACE_URI, PROP_NTH_SIBLING);
/**
* Versioned assoc type
*/
public static final String TYPE_VERSIONED_ASSOC = "versionedAssoc";
public static final QName TYPE_QNAME_VERSIONED_ASSOC = QName.createQName(NAMESPACE_URI, TYPE_VERSIONED_ASSOC);
/**
* Child relationship names
*/
public static final String CHILD_VERSION_HISTORIES = "versionHistory";
public static final String CHILD_VERSIONS = "version";
public static final String CHILD_VERSIONED_ATTRIBUTES = "versionedAttributes";
public static final String CHILD_VERSIONED_CHILD_ASSOCS = "versionedChildAssocs";
public static final String CHILD_VERSIONED_ASSOCS = "versionedAssocs";
public static final String CHILD_VERSION_META_DATA = "versionMetaData";
public static final QName CHILD_QNAME_VERSION_HISTORIES = QName.createQName(NAMESPACE_URI, CHILD_VERSION_HISTORIES);
public static final QName CHILD_QNAME_VERSIONS = QName.createQName(NAMESPACE_URI, CHILD_VERSIONS);
public static final QName CHILD_QNAME_VERSIONED_ATTRIBUTES = QName.createQName(NAMESPACE_URI, CHILD_VERSIONED_ATTRIBUTES);
public static final QName CHILD_QNAME_VERSIONED_CHILD_ASSOCS = QName.createQName(NAMESPACE_URI, CHILD_VERSIONED_CHILD_ASSOCS);
public static final QName CHILD_QNAME_VERSIONED_ASSOCS = QName.createQName(NAMESPACE_URI, CHILD_VERSIONED_ASSOCS);
public static final QName CHILD_QNAME_VERSION_META_DATA = QName.createQName(NAMESPACE_URI, CHILD_VERSION_META_DATA);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,466 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version;
import java.util.Collection;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.transaction.TransactionUtil;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionHistory;
import org.alfresco.service.cmr.version.VersionServiceException;
import org.alfresco.service.namespace.QName;
/**
* versionService test class.
*
* @author Roy Wetherall
*/
public class VersionServiceImplTest extends BaseVersionStoreTest
{
private static final String UPDATED_VALUE_1 = "updatedValue1";
private static final String UPDATED_VALUE_2 = "updatedValue2";
private static final String UPDATED_VALUE_3 = "updatedValue3";
private static final String UPDATED_CONTENT_1 = "updatedContent1";
private static final String UPDATED_CONTENT_2 = "updatedContent2";
/**
* Tests the creation of the initial version of a versionable node
*/
public void testCreateIntialVersion()
{
NodeRef versionableNode = createNewVersionableNode();
createVersion(versionableNode);
}
/**
* Test creating a version history with many versions from the same workspace
*/
public void testCreateManyVersionsSameWorkspace()
{
NodeRef versionableNode = createNewVersionableNode();
createVersion(versionableNode);
// TODO mess with some of the properties and stuff as you version
createVersion(versionableNode);
// TODO mess with some of the properties and stuff as you version
createVersion(versionableNode);
}
// TODO test versioning a non versionable node ie: no version apsect
// TODO test versioning numberious times with branchs implies by different workspaces
/**
* Test versioning the children of a verionable node
*/
public void testVersioningChildren()
{
NodeRef versionableNode = createNewVersionableNode();
// Snap shot data
int expectedVersionNumber = peekNextVersionNumber();
String expectedVersionLabel = peekNextVersionLabel(versionableNode, expectedVersionNumber, versionProperties);
long beforeVersionTime = System.currentTimeMillis();
// Version the node and its children
Collection<Version> versions = this.versionService.createVersion(
versionableNode,
this.versionProperties,
true);
// Check the returned versions are correct
CheckVersionCollection(expectedVersionNumber, expectedVersionLabel, beforeVersionTime, versions);
// TODO check the version history is correct
}
/**
* Test versioning many nodes in one go
*/
public void testVersioningManyNodes()
{
NodeRef versionableNode = createNewVersionableNode();
// Snap shot data
int expectedVersionNumber = peekNextVersionNumber();
String expectedVersionLabel = peekNextVersionLabel(versionableNode, expectedVersionNumber, versionProperties);
long beforeVersionTime = System.currentTimeMillis();
// Version the list of nodes created
Collection<Version> versions = this.versionService.createVersion(
this.versionableNodes.values(),
this.versionProperties);
// Check the returned versions are correct
CheckVersionCollection(expectedVersionNumber, expectedVersionLabel, beforeVersionTime, versions);
// TODO check the version histories
}
/**
* Helper method to check the validity of the list of newly created versions.
*
* @param expectedVersionNumber the expected version number that all the versions should have
* @param beforeVersionTime the time before the versions where created
* @param versions the collection of version objects
*/
private void CheckVersionCollection(int expectedVersionNumber, String expectedVersionLabel, long beforeVersionTime, Collection<Version> versions)
{
for (Version version : versions)
{
// Get the frozen id from the version
String frozenNodeId = (String)version.getVersionProperty(VersionModel.PROP_FROZEN_NODE_ID);
assertNotNull("Unable to retrieve the frozen node id from the created version.", frozenNodeId);
// Get the origional node ref (based on the forzen node)
NodeRef origionaNodeRef = this.versionableNodes.get(frozenNodeId);
assertNotNull("The versionable node ref that relates to the frozen node id can not be found.", origionaNodeRef);
// Check the new version
checkNewVersion(beforeVersionTime, expectedVersionNumber, expectedVersionLabel, version, origionaNodeRef);
}
}
/**
* Tests the version history
*/
public void testNoVersionHistory()
{
NodeRef nodeRef = createNewVersionableNode();
VersionHistory vh = this.versionService.getVersionHistory(nodeRef);
assertNull(vh);
}
/**
* Tests getVersionHistory when all the entries in the version history
* are from the same workspace.
*/
public void testGetVersionHistorySameWorkspace()
{
NodeRef versionableNode = createNewVersionableNode();
Version version1 = addToVersionHistory(versionableNode, null);
Version version2 = addToVersionHistory(versionableNode, version1);
Version version3 = addToVersionHistory(versionableNode, version2);
Version version4 = addToVersionHistory(versionableNode, version3);
addToVersionHistory(versionableNode, version4);
}
/**
* Adds another version to the version history then checks that getVersionHistory is returning
* the correct data.
*
* @param versionableNode the versionable node reference
* @param parentVersion the parent version
*/
private Version addToVersionHistory(NodeRef versionableNode, Version parentVersion)
{
Version createdVersion = createVersion(versionableNode);
VersionHistory vh = this.versionService.getVersionHistory(versionableNode);
assertNotNull("The version history should not be null since we know we have versioned this node.", vh);
if (parentVersion == null)
{
// Check the root is the newly created version
Version root = vh.getRootVersion();
assertNotNull(
"The root version should never be null, since every version history ust have a root version.",
root);
assertEquals(createdVersion.getVersionLabel(), root.getVersionLabel());
}
// Get the version from the version history
Version version = vh.getVersion(createdVersion.getVersionLabel());
assertNotNull(version);
assertEquals(createdVersion.getVersionLabel(), version.getVersionLabel());
// Check that the version is a leaf node of the version history (since it is newly created)
Collection<Version> suc = vh.getSuccessors(version);
assertNotNull(suc);
assertEquals(0, suc.size());
// Check that the predessor is the passed parent version (if root version should be null)
Version pre = vh.getPredecessor(version);
if (parentVersion == null)
{
assertNull(pre);
}
else
{
assertNotNull(pre);
assertEquals(parentVersion.getVersionLabel(), pre.getVersionLabel());
}
if (parentVersion != null)
{
// Check that the successors of the parent are the created version
Collection<Version> parentSuc = vh.getSuccessors(parentVersion);
assertNotNull(parentSuc);
assertEquals(1, parentSuc.size());
Version tempVersion = (Version)parentSuc.toArray()[0];
assertEquals(version.getVersionLabel(), tempVersion.getVersionLabel());
}
return createdVersion;
}
/**
* Test revert
*/
@SuppressWarnings("unused")
public void testRevert()
{
// Create a versionable node
NodeRef versionableNode = createNewVersionableNode();
// Store the node details for later
Set<QName> origAspects = this.dbNodeService.getAspects(versionableNode);
// Create the initial version
Version version1 = createVersion(versionableNode);
// Change the property and content values
this.dbNodeService.setProperty(versionableNode, PROP_1, UPDATED_VALUE_1);
this.dbNodeService.setProperty(versionableNode, PROP_2, null);
ContentWriter contentWriter = this.contentService.getWriter(versionableNode, ContentModel.PROP_CONTENT, true);
assertNotNull(contentWriter);
contentWriter.putContent(UPDATED_CONTENT_1);
// Change the aspects on the node
this.dbNodeService.addAspect(versionableNode, ContentModel.ASPECT_SIMPLE_WORKFLOW, null);
// Store the node details for later
Set<QName> origAspects2 = this.dbNodeService.getAspects(versionableNode);
// Create a new version
Version version2 = createVersion(versionableNode);
// Change the property and content values
this.dbNodeService.setProperty(versionableNode, PROP_1, UPDATED_VALUE_2);
this.dbNodeService.setProperty(versionableNode, PROP_2, UPDATED_VALUE_3);
this.dbNodeService.setProperty(versionableNode, PROP_3, null);
ContentWriter contentWriter2 = this.contentService.getWriter(versionableNode, ContentModel.PROP_CONTENT, true);
assertNotNull(contentWriter2);
contentWriter2.putContent(UPDATED_CONTENT_2);
String versionLabel = (String)this.dbNodeService.getProperty(versionableNode, ContentModel.PROP_VERSION_LABEL);
// Revert to the previous version
this.versionService.revert(versionableNode);
// Check that the version label is unchanged
assertEquals(versionLabel, this.dbNodeService.getProperty(versionableNode, ContentModel.PROP_VERSION_LABEL));
// Check that the properties have been reverted
assertEquals(UPDATED_VALUE_1, this.dbNodeService.getProperty(versionableNode, PROP_1));
assertNull(this.dbNodeService.getProperty(versionableNode, PROP_2));
assertEquals(VALUE_3, this.dbNodeService.getProperty(versionableNode, PROP_3));
// Check that the content has been reverted
ContentReader contentReader1 = this.contentService.getReader(versionableNode, ContentModel.PROP_CONTENT);
assertNotNull(contentReader1);
assertEquals(UPDATED_CONTENT_1, contentReader1.getContentString());
// Check that the aspects have been reverted correctly
Set<QName> aspects1 = this.dbNodeService.getAspects(versionableNode);
assertEquals(aspects1.size(), origAspects2.size());
// Revert to the first version
this.versionService.revert(versionableNode, version1);
// Check that the version label is correct
assertEquals(versionLabel, this.dbNodeService.getProperty(versionableNode, ContentModel.PROP_VERSION_LABEL));
// Check that the properties are correct
assertEquals(VALUE_1, this.dbNodeService.getProperty(versionableNode, PROP_1));
assertEquals(VALUE_2, this.dbNodeService.getProperty(versionableNode, PROP_2));
assertEquals(VALUE_3, this.dbNodeService.getProperty(versionableNode, PROP_3));
// Check that the content is correct
ContentReader contentReader2 = this.contentService.getReader(versionableNode, ContentModel.PROP_CONTENT);
assertNotNull(contentReader2);
assertEquals(TEST_CONTENT, contentReader2.getContentString());
// Check that the aspects have been reverted correctly
Set<QName> aspects2 = this.dbNodeService.getAspects(versionableNode);
assertEquals(aspects2.size(), origAspects.size());
// Check that the version label is still the same
assertEquals(versionLabel, this.dbNodeService.getProperty(versionableNode, ContentModel.PROP_VERSION_LABEL));
}
/**
* Test restore
*/
public void testRestore()
{
// Try and restore a node without any version history
try
{
this.versionService.restore(
new NodeRef(this.testStoreRef, "123"),
rootNodeRef,
ContentModel.ASSOC_CHILDREN,
QName.createQName("{test}MyVersionableNode"));
fail("An exception should have been raised since this node has no version history.");
}
catch (VersionServiceException exception)
{
// We where expecting this exception
}
// Create a versionable node
NodeRef versionableNode = createNewVersionableNode();
// Store the node details for later
Set<QName> origAspects = this.dbNodeService.getAspects(versionableNode);
// Try and restore the node (fail since exist!!)
try
{
this.versionService.restore(
versionableNode,
rootNodeRef,
ContentModel.ASSOC_CHILDREN,
QName.createQName("{test}MyVersionableNode"));
fail("An exception should have been raised since this node exists and you can't restore a node that exists.");
}
catch (VersionServiceException exception)
{
// We where expecting this exception
}
// Version it
this.versionService.createVersion(versionableNode, null);
// Delete it
this.dbNodeService.deleteNode(versionableNode);
assertFalse(this.dbNodeService.exists(versionableNode));
// Try and resotre it
NodeRef restoredNode = this.versionService.restore(
versionableNode,
this.rootNodeRef,
ContentModel.ASSOC_CHILDREN,
QName.createQName("{test}MyVersionableNode"));
assertNotNull(restoredNode);
assertTrue(this.dbNodeService.exists(restoredNode));
// Check that the properties are correct
assertEquals(VALUE_1, this.dbNodeService.getProperty(restoredNode, PROP_1));
assertEquals(VALUE_2, this.dbNodeService.getProperty(restoredNode, PROP_2));
assertEquals(VALUE_3, this.dbNodeService.getProperty(restoredNode, PROP_3));
// Check that the content is correct
ContentReader contentReader2 = this.contentService.getReader(restoredNode, ContentModel.PROP_CONTENT);
assertNotNull(contentReader2);
assertEquals(TEST_CONTENT, contentReader2.getContentString());
// Check that the aspects have been reverted correctly
Set<QName> aspects2 = this.dbNodeService.getAspects(restoredNode);
assertEquals(aspects2.size(), origAspects.size());
}
/**
* Test deleteVersionHistory
*/
public void testDeleteVersionHistory()
{
// Create a versionable node
NodeRef versionableNode = createNewVersionableNode();
// Check that there is no version history
VersionHistory versionHistory1 = this.versionService.getVersionHistory(versionableNode);
assertNull(versionHistory1);
// Create a couple of versions
createVersion(versionableNode);
Version version1 = createVersion(versionableNode);
// Check that the version label is correct on the versionable node
String versionLabel1 = (String)this.dbNodeService.getProperty(versionableNode, ContentModel.PROP_VERSION_LABEL);
assertNotNull(versionLabel1);
assertEquals(version1.getVersionLabel(), versionLabel1);
// Check that the version history has been created correctly
VersionHistory versionHistory2 = this.versionService.getVersionHistory(versionableNode);
assertNotNull(versionHistory2);
assertEquals(2, versionHistory2.getAllVersions().size());
// Delete the version history
this.versionService.deleteVersionHistory(versionableNode);
// Check that there is no version history available for the node
VersionHistory versionHistory3 = this.versionService.getVersionHistory(versionableNode);
assertNull(versionHistory3);
// Check that the current version property on the versionable node is no longer set
String versionLabel2 = (String)this.dbNodeService.getProperty(versionableNode, ContentModel.PROP_VERSION_LABEL);
assertNull(versionLabel2);
// Create a couple of versions
createVersion(versionableNode);
Version version2 = createVersion(versionableNode);
// Check that the version history is correct
VersionHistory versionHistory4 = this.versionService.getVersionHistory(versionableNode);
assertNotNull(versionHistory4);
assertEquals(2, versionHistory4.getAllVersions().size());
// Check that the version label is correct on the versionable node
String versionLabel3 = (String)this.dbNodeService.getProperty(versionableNode, ContentModel.PROP_VERSION_LABEL);
assertNotNull(versionLabel3);
assertEquals(version2.getVersionLabel(), versionLabel3);
}
public void testAutoVersion()
{
// Create a versionable node
final NodeRef versionableNode = createNewVersionableNode();
// Add some content
ContentWriter contentWriter = this.contentService.getWriter(versionableNode, ContentModel.PROP_CONTENT, true);
assertNotNull(contentWriter);
contentWriter.putContent(UPDATED_CONTENT_1);
// Need to commit in order to get the auto version to fire ...
setComplete();
endTransaction();
// Now lets have a look and make sure we have the correct number of entries in the version history
TransactionUtil.executeInUserTransaction(this.transactionService, new TransactionUtil.TransactionWork<Object>()
{
public Object doWork() throws Exception
{
VersionHistory versionHistory = VersionServiceImplTest.this.versionService.getVersionHistory(versionableNode);
assertNotNull(versionHistory);
assertEquals(1, versionHistory.getAllVersions().size());
return null;
}
});
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.repo.policy.ClassPolicy;
import org.alfresco.repo.policy.PolicyScope;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.namespace.QName;
/**
* Version service policy interfaces
*
* @author Roy Wetherall
*/
public interface VersionServicePolicies
{
/**
* Before create version policy interface.
*/
public interface BeforeCreateVersionPolicy extends ClassPolicy
{
/**
* Called before a new version is created for a version
*
* @param versionableNode reference to the node about to be versioned
*/
public void beforeCreateVersion(NodeRef versionableNode);
}
/**
* On create version policy interface
*/
public interface OnCreateVersionPolicy extends ClassPolicy
{
public void onCreateVersion(
QName classRef,
NodeRef versionableNode,
Map<String, Serializable> versionProperties,
PolicyScope nodeDetails);
}
/**
* Calculate version lable policy interface
*/
public interface CalculateVersionLabelPolicy extends ClassPolicy
{
public String calculateVersionLabel(
QName classRef,
Version preceedingVersion,
int versionNumber,
Map<String, Serializable>verisonProperties);
}
}

View File

@@ -0,0 +1,112 @@
<model name="test:versionstorebasetestmodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
<description>VersionStoreBaseTest model</description>
<author>Alfresco</author>
<published>2005-05-30</published>
<version>1.0</version>
<imports>
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
</imports>
<namespaces>
<namespace uri="http://www.alfresco.org/test/versionstorebasetest/1.0" prefix="test"/>
</namespaces>
<types>
<type name="test:testtype">
<title>Test type</title>
<description>The test type</description>
<parent>cm:content</parent>
<properties>
<property name="test:prop1">
<type>d:text</type>
<protected>false</protected>
<default></default>
</property>
<property name="test:prop2">
<type>d:text</type>
<protected>false</protected>
<default></default>
</property>
<property name="test:prop3">
<type>d:text</type>
<protected>false</protected>
<default></default>
</property>
<property name="test:multiProp">
<type>d:text</type>
<multiple>true</multiple>
</property>
</properties>
<associations>
<association name="test:assoc1">
<source>
<mandatory>false</mandatory>
<many>false</many>
</source>
<target>
<class>test:testtype</class>
<mandatory>false</mandatory>
<many>true</many>
</target>
</association>
<child-association name="test:childassoc1">
<source>
<mandatory>false</mandatory>
<many>true</many>
</source>
<target>
<class>test:testtype</class>
<mandatory>false</mandatory>
<many>false</many>
</target>
<child-name>childassoc1</child-name>
<duplicate>true</duplicate>
</child-association>
<child-association name="test:childassoc2">
<source>
<mandatory>false</mandatory>
<many>true</many>
</source>
<target>
<class>test:testtype</class>
<mandatory>false</mandatory>
<many>false</many>
</target>
<child-name>childassoc2</child-name>
<duplicate>true</duplicate>
</child-association>
</associations>
</type>
</types>
<aspects>
<aspect name="test:testaspect">
<title>Test Aspect</title>
<description>The test aspect</description>
<parent></parent>
<properties>
<property name="test:aspectprop1">
<type>d:text</type>
<protected>false</protected>
<default></default>
</property>
<property name="test:aspectprop2">
<type>d:text</type>
<protected>false</protected>
<default></default>
</property>
</properties>
</aspect>
</aspects>
</model>

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.alfresco.repo.version.common.VersionHistoryImplTest;
import org.alfresco.repo.version.common.VersionImplTest;
import org.alfresco.repo.version.common.counter.VersionCounterDaoServiceTest;
import org.alfresco.repo.version.common.versionlabel.SerialVersionLabelPolicyTest;
/**
* Version test suite
*
* @author Roy Wetherall
*/
public class VersionTestSuite extends TestSuite
{
/**
* Creates the test suite
*
* @return the test suite
*/
public static Test suite()
{
TestSuite suite = new TestSuite();
suite.addTestSuite(VersionImplTest.class);
suite.addTestSuite(VersionHistoryImplTest.class);
suite.addTestSuite(SerialVersionLabelPolicyTest.class);
suite.addTestSuite(VersionCounterDaoServiceTest.class);
suite.addTestSuite(VersionServiceImplTest.class);
suite.addTestSuite(NodeServiceImplTest.class);
suite.addTestSuite(ContentServiceImplTest.class);
return suite;
}
}

View File

@@ -0,0 +1,272 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.evaluator.HasVersionHistoryEvaluator;
import org.alfresco.repo.action.executer.CreateVersionActionExecuter;
import org.alfresco.repo.policy.Behaviour;
import org.alfresco.repo.policy.BehaviourDefinition;
import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.policy.PolicyScope;
import org.alfresco.repo.rule.RuntimeRuleService;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ActionCondition;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.rule.Rule;
import org.alfresco.service.cmr.rule.RuleService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
/**
* Class containing behaviour for the versionable aspect
*
* @author Roy Wetherall
*/
public class VersionableAspect
{
/**
* The policy component
*/
private PolicyComponent policyComponent;
/**
* The node service
*/
private NodeService nodeService;
/**
* The rule service
*/
private RuleService ruleService;
/**
* The action service
*/
private ActionService actionService;
/**
* The rule used to create versions
*/
private Rule rule;
/**
* Auto version behaviour
*/
private Behaviour autoVersionBehaviour;
/**
* Set the policy component
*
* @param policyComponent the policy component
*/
public void setPolicyComponent(PolicyComponent policyComponent)
{
this.policyComponent = policyComponent;
}
/**
* Set the rule service
*
* @param ruleService the rule service
*/
public void setRuleService(RuleService ruleService)
{
this.ruleService = ruleService;
}
/**
* Set the action service
*
* @param actionService the action service
*/
public void setActionService(ActionService actionService)
{
this.actionService = actionService;
}
/**
* Set the node service
*
* @param nodeService the node service
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* Initialise the versionable aspect policies
*/
public void init()
{
this.policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "onAddAspect"),
ContentModel.ASPECT_VERSIONABLE,
new JavaBehaviour(this, "onAddAspect"));
autoVersionBehaviour = new JavaBehaviour(this, "onContentUpdate");
this.policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "onContentUpdate"),
ContentModel.ASPECT_VERSIONABLE,
autoVersionBehaviour);
// Register the copy behaviour
this.policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "onCopyNode"),
ContentModel.ASPECT_VERSIONABLE,
new JavaBehaviour(this, "onCopy"));
// Register the onCreateVersion behavior for the version aspect
//this.policyComponent.bindClassBehaviour(
// QName.createQName(NamespaceService.ALFRESCO_URI, "onCreateVersion"),
// ContentModel.ASPECT_VERSIONABLE,
// new JavaBehaviour(this, "onCreateVersion"));
}
/**
* OnCopy behaviour implementation for the version aspect.
* <p>
* Ensures that the propety values of the version aspect are not copied onto
* the destination node.
*
* @see org.alfresco.repo.copy.CopyServicePolicies.OnCopyNodePolicy#onCopyNode(QName, NodeRef, StoreRef, boolean, PolicyScope)
*/
public void onCopy(
QName sourceClassRef,
NodeRef sourceNodeRef,
StoreRef destinationStoreRef,
boolean copyToNewNode,
PolicyScope copyDetails)
{
// Add the version aspect, but do not copy the version label
copyDetails.addAspect(ContentModel.ASPECT_VERSIONABLE);
copyDetails.addProperty(
ContentModel.ASPECT_VERSIONABLE,
ContentModel.PROP_AUTO_VERSION,
this.nodeService.getProperty(sourceNodeRef, ContentModel.PROP_AUTO_VERSION));
}
/**
* OnCreateVersion behaviour for the version aspect
* <p>
* Ensures that the version aspect and it proerties are 'frozen' as part of
* the versioned state.
*
* @param classRef the class reference
* @param versionableNode the versionable node reference
* @param versionProperties the version properties
* @param nodeDetails the details of the node to be versioned
*/
public void onCreateVersion(
QName classRef,
NodeRef versionableNode,
Map<String, Serializable> versionProperties,
PolicyScope nodeDetails)
{
// Do nothing since we do not what to freeze any of the version
// properties
}
/**
* On add aspect policy behaviour
*
* @param nodeRef
* @param aspectTypeQName
*/
@SuppressWarnings("unchecked")
public void onAddAspect(NodeRef nodeRef, QName aspectTypeQName)
{
if (aspectTypeQName.equals(ContentModel.ASPECT_VERSIONABLE) == true)
{
// Queue create version action
queueCreateVersionAction(nodeRef);
}
}
/**
* On content update policy bahaviour
*
* @param nodeRef the node reference
*/
public void onContentUpdate(NodeRef nodeRef)
{
if (this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE) == true)
{
// Determine whether the node is auto versionable or not
boolean autoVersion = false;
Boolean value = (Boolean)this.nodeService.getProperty(nodeRef, ContentModel.PROP_AUTO_VERSION);
if (value != null)
{
// If the value is not null then
autoVersion = value.booleanValue();
}
// else this means that the default value has not been set and the versionable aspect was applied pre-1.1
if (autoVersion == true)
{
// Queue create version action
queueCreateVersionAction(nodeRef);
}
}
}
/**
* Enable the auto version behaviour
*
*/
public void enableAutoVersion()
{
this.autoVersionBehaviour.enable();
}
/**
* Disable the auto version behaviour
*
*/
public void disableAutoVersion()
{
this.autoVersionBehaviour.disable();
}
/**
* Queue create version action
*
* @param nodeRef the node reference
*/
private void queueCreateVersionAction(NodeRef nodeRef)
{
if (this.rule == null)
{
this.rule = this.ruleService.createRule("inbound");
Action action = this.actionService.createAction(CreateVersionActionExecuter.NAME);
ActionCondition condition = this.actionService.createActionCondition(HasVersionHistoryEvaluator.NAME);
condition.setInvertCondition(true);
action.addActionCondition(condition);
this.rule.addAction(action);
}
((RuntimeRuleService)this.ruleService).addRulePendingExecution(nodeRef, nodeRef, this.rule, true);
}
}

View File

@@ -0,0 +1,281 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version.common;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.repo.policy.ClassPolicyDelegate;
import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.policy.PolicyScope;
import org.alfresco.repo.version.VersionServicePolicies;
import org.alfresco.repo.version.VersionServicePolicies.BeforeCreateVersionPolicy;
import org.alfresco.repo.version.VersionServicePolicies.CalculateVersionLabelPolicy;
import org.alfresco.repo.version.VersionServicePolicies.OnCreateVersionPolicy;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
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.version.Version;
import org.alfresco.service.cmr.version.VersionServiceException;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
/**
* Abstract version service implementation.
*
* @author Roy Wetherall
*/
public abstract class AbstractVersionServiceImpl
{
/**
* The common node service
*/
protected NodeService nodeService ;
/**
* Policy component
*/
protected PolicyComponent policyComponent;
/**
* The dictionary service
*/
protected DictionaryService dictionaryService;
/**
* Policy delegates
*/
private ClassPolicyDelegate<BeforeCreateVersionPolicy> beforeCreateVersionDelegate;
private ClassPolicyDelegate<OnCreateVersionPolicy> onCreateVersionDelegate;
private ClassPolicyDelegate<CalculateVersionLabelPolicy> calculateVersionLabelDelegate;
/**
* Sets the general node service
*
* @param nodeService the node service
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* Sets the policy component
*
* @param policyComponent the policy component
*/
public void setPolicyComponent(PolicyComponent policyComponent)
{
this.policyComponent = policyComponent;
}
/**
* Sets the dictionary service
*
* @param dictionaryService the dictionary service
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* Initialise method
*/
public void initialise()
{
// Register the policies
this.beforeCreateVersionDelegate = this.policyComponent.registerClassPolicy(VersionServicePolicies.BeforeCreateVersionPolicy.class);
this.onCreateVersionDelegate = this.policyComponent.registerClassPolicy(VersionServicePolicies.OnCreateVersionPolicy.class);
this.calculateVersionLabelDelegate = this.policyComponent.registerClassPolicy(VersionServicePolicies.CalculateVersionLabelPolicy.class);
}
/**
* Invokes the before create version policy behaviour
*
* @param nodeRef the node being versioned
*/
protected void invokeBeforeCreateVersion(NodeRef nodeRef)
{
// invoke for node type
QName nodeTypeQName = nodeService.getType(nodeRef);
this.beforeCreateVersionDelegate.get(nodeTypeQName).beforeCreateVersion(nodeRef);
// invoke for node aspects
Set<QName> nodeAspectQNames = nodeService.getAspects(nodeRef);
this.beforeCreateVersionDelegate.get(nodeAspectQNames).beforeCreateVersion(nodeRef);
}
/**
* Invoke the on create version policy behaviour
*
*/
protected void invokeOnCreateVersion(
NodeRef nodeRef,
Map<String, Serializable> versionProperties,
PolicyScope nodeDetails)
{
// Sort out the policies for the node type
QName classRef = this.nodeService.getType(nodeRef);
invokeOnCreateVersion(classRef, nodeRef, versionProperties, nodeDetails);
// Sort out the policies for the aspects
Collection<QName> aspects = this.nodeService.getAspects(nodeRef);
for (QName aspect : aspects)
{
invokeOnCreateVersion(aspect, nodeRef, versionProperties, nodeDetails);
}
}
/**
* Invokes the on create version policy behaviour for a given type
*
* @param classRef
* @param nodeDetails
* @param nodeRef
* @param versionProperties
*/
private void invokeOnCreateVersion(
QName classRef,
NodeRef nodeRef,
Map<String, Serializable> versionProperties,
PolicyScope nodeDetails)
{
Collection<OnCreateVersionPolicy> policies = this.onCreateVersionDelegate.getList(classRef);
if (policies.size() == 0)
{
// Call the default implementation
defaultOnCreateVersion(
classRef,
nodeRef,
versionProperties,
nodeDetails);
}
else
{
// Call the policy definitions
for (VersionServicePolicies.OnCreateVersionPolicy policy : policies)
{
policy.onCreateVersion(
classRef,
nodeRef,
versionProperties,
nodeDetails);
}
}
}
/**
* Default implementation of the on create version policy. Called if no behaviour is registered for the
* policy for the specified type.
*
* @param nodeRef
* @param versionProperties
* @param nodeDetails
*/
protected void defaultOnCreateVersion(
QName classRef,
NodeRef nodeRef,
Map<String, Serializable> versionProperties,
PolicyScope nodeDetails)
{
ClassDefinition classDefinition = this.dictionaryService.getClass(classRef);
if (classDefinition != null)
{
// Copy the properties
Map<QName,PropertyDefinition> propertyDefinitions = classDefinition.getProperties();
for (QName propertyName : propertyDefinitions.keySet())
{
Serializable propValue = this.nodeService.getProperty(nodeRef, propertyName);
nodeDetails.addProperty(classRef, propertyName, propValue);
}
// Version the associations (child and target)
Map<QName, AssociationDefinition> assocDefs = classDefinition.getAssociations();
// TODO: Need way of getting child assocs of a given type
if (classDefinition.isContainer())
{
List<ChildAssociationRef> childAssocRefs = this.nodeService.getChildAssocs(nodeRef);
for (ChildAssociationRef childAssocRef : childAssocRefs)
{
if (assocDefs.containsKey(childAssocRef.getTypeQName()))
{
nodeDetails.addChildAssociation(classDefinition.getName(), childAssocRef);
}
}
}
// TODO: Need way of getting assocs of a given type
List<AssociationRef> nodeAssocRefs = this.nodeService.getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL);
for (AssociationRef nodeAssocRef : nodeAssocRefs)
{
if (assocDefs.containsKey(nodeAssocRef.getTypeQName()))
{
nodeDetails.addAssociation(classDefinition.getName(), nodeAssocRef);
}
}
}
}
/**
* Invoke the calculate version label policy behaviour
*
* @param classRef
* @param preceedingVersion
* @param versionNumber
* @param versionProperties
* @return
*/
protected String invokeCalculateVersionLabel(
QName classRef,
Version preceedingVersion,
int versionNumber,
Map<String, Serializable>versionProperties)
{
String versionLabel = null;
Collection<CalculateVersionLabelPolicy> behaviours = this.calculateVersionLabelDelegate.getList(classRef);
if (behaviours.size() == 0)
{
// Default the version label to the version numbder
versionLabel = Integer.toString(versionNumber);
}
else if (behaviours.size() == 1)
{
// Call the policy behaviour
CalculateVersionLabelPolicy[] arr = behaviours.toArray(new CalculateVersionLabelPolicy[]{});
versionLabel = arr[0].calculateVersionLabel(classRef, preceedingVersion, versionNumber, versionProperties);
}
else
{
// Error since we can only deal with a single caculate version label policy
throw new VersionServiceException("More than one CalculateVersionLabelPolicy behaviour has been registered for the type " + classRef.toString());
}
return versionLabel;
}
}

View File

@@ -0,0 +1,195 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version.common;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionDoesNotExistException;
import org.alfresco.service.cmr.version.VersionHistory;
import org.alfresco.service.cmr.version.VersionServiceException;
/**
* Version History implementation.
*
* @author Roy Wetherall
*/
public class VersionHistoryImpl implements VersionHistory
{
/*
* Serial version UID
*/
private static final long serialVersionUID = 3257001051558326840L;
/*
* Error message(s)
*/
private static final String ERR_MSG = "The root version must be specified when creating a version history object.";
/*
* The root version label
*/
private String rootVersionLabel = null;
/*
* Version history tree structure map
*/
private HashMap<String, String> versionHistory = null;
/*
* Label to version object map
*/
private HashMap<String, Version> versions = null;
private Version rootVersion;
/**
* Constructor, ensures the root version is set.
*
* @param rootVersion the root version, can not be null.
*/
public VersionHistoryImpl(Version rootVersion)
{
if (rootVersion == null)
{
// Exception - a version history can not be created unless
// a root version is specified
throw new VersionServiceException(VersionHistoryImpl.ERR_MSG);
}
this.versionHistory = new HashMap<String, String>();
this.versions = new HashMap<String, Version>();
this.rootVersion = rootVersion;
this.rootVersionLabel = rootVersion.getVersionLabel();
addVersion(rootVersion, null);
}
/**
* Gets the root (or initial) version of the version history.
*
* @return the root version
*/
public Version getRootVersion()
{
return this.rootVersion;
}
/**
* Gets a collection containing all the versions within the
* version history.
* <p>
* The order of the versions is not guarenteed.
*
* @return collection containing all the versions
*/
public Collection<Version> getAllVersions()
{
return this.versions.values();
}
/**
* Gets the predecessor of a specified version
*
* @param version the version object
* @return the predeceeding version, null if root version
*/
public Version getPredecessor(Version version)
{
Version result = null;
if (version != null)
{
result = getVersion(this.versionHistory.get(version.getVersionLabel()));
}
return result;
}
/**
* Gets the succeeding versions of a specified version.
*
* @param version the version object
* @return a collection containing the succeeding version, empty is none
*/
public Collection<Version> getSuccessors(Version version)
{
ArrayList<Version> result = new ArrayList<Version>();
if (version != null)
{
String versionLabel = version.getVersionLabel();
if (this.versionHistory.containsValue(versionLabel) == true)
{
for (String key : this.versionHistory.keySet())
{
if (this.versionHistory.get(key) == versionLabel)
{
result.add(getVersion(key));
}
}
}
}
return result;
}
/**
* Gets a version with a specified version label. The version label is guarenteed
* unique within the version history.
*
* @param versionLabel the version label
* @return the version object
* @throws VersionDoesNotExistException indicates requested version does not exisit
*/
public Version getVersion(String versionLabel)
{
Version result = null;
if (versionLabel != null)
{
result = this.versions.get(versionLabel);
if (result == null)
{
// Throw exception indicating that the version does not exit
throw new VersionDoesNotExistException(versionLabel);
}
}
return result;
}
/**
* Add a version to the version history.
* <p>
* Used internally to build the version history tree.
*
* @param version the version object
* @param predecessor the preceeding version
*/
public void addVersion(Version version, Version predecessor)
{
// TODO cope with exception case where duplicate version labels have been specified
this.versions.put(version.getVersionLabel(), version);
if (predecessor != null)
{
this.versionHistory.put(version.getVersionLabel(), predecessor.getVersionLabel());
}
}
}

View File

@@ -0,0 +1,255 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version.common;
import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import junit.framework.TestCase;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionDoesNotExistException;
import org.alfresco.service.cmr.version.VersionServiceException;
/**
* VersionHistoryImpl Unit Test Class
*
* @author Roy Wetherall
*/
public class VersionHistoryImplTest extends TestCase
{
/**
* Data used in the tests
*/
private Version rootVersion = null;
private Version childVersion1 = null;
private Version childVersion2 = null;
/**
* Set up
*/
protected void setUp() throws Exception
{
super.setUp();
// Create dummy node ref
NodeRef nodeRef = new NodeRef(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "test"), "test");
HashMap<String, Serializable> versionProperties1 = new HashMap<String, Serializable>();
versionProperties1.put(VersionModel.PROP_VERSION_LABEL, "1");
versionProperties1.put(VersionModel.PROP_CREATED_DATE, new Date());
versionProperties1.put("testProperty", "testValue");
this.rootVersion = new VersionImpl(versionProperties1, nodeRef);
HashMap<String, Serializable> versionProperties2 = new HashMap<String, Serializable>();
versionProperties2.put(VersionModel.PROP_VERSION_LABEL, "2");
versionProperties2.put(VersionModel.PROP_CREATED_DATE, new Date());
versionProperties2.put("testProperty", "testValue");
this.childVersion1 = new VersionImpl(versionProperties2, nodeRef);
HashMap<String, Serializable> versionProperties3 = new HashMap<String, Serializable>();
versionProperties3.put(VersionModel.PROP_VERSION_LABEL, "3");
versionProperties3.put(VersionModel.PROP_CREATED_DATE, new Date());
versionProperties3.put("testProperty", "testValue");
this.childVersion2 = new VersionImpl(versionProperties3, nodeRef);
}
/**
* Test constructor
*/
public void testConstructor()
{
testContructorImpl();
}
/**
* Test construtor helper
*
* @return new version history
*/
private VersionHistoryImpl testContructorImpl()
{
VersionHistoryImpl vh = new VersionHistoryImpl(this.rootVersion);
assertNotNull(vh);
return vh;
}
/**
* Exception case - a root version must be specified when creating a
* version history object
*/
public void testRootVersionSpecified()
{
try
{
new VersionHistoryImpl(null);
fail();
}
catch(VersionServiceException exception)
{
}
}
/**
* Test getRootVersion
*
*@return root version
*/
public void testGetRootVersion()
{
VersionHistoryImpl vh = testContructorImpl();
Version rootVersion = vh.getRootVersion();
assertNotNull(rootVersion);
assertEquals(rootVersion, this.rootVersion);
}
/**
* Test getAllVersions
*/
public void testGetAllVersions()
{
VersionHistoryImpl vh = testAddVersionImpl();
Collection<Version> allVersions = vh.getAllVersions();
assertNotNull(allVersions);
assertEquals(3, allVersions.size());
}
/**
* Test addVersion
*
* @return version history
*/
public void testAddVersion()
{
testAddVersionImpl();
}
/**
* Test addVersion helper
*
* @return version history with version tree built
*/
private VersionHistoryImpl testAddVersionImpl()
{
VersionHistoryImpl vh = testContructorImpl();
Version rootVersion = vh.getRootVersion();
vh.addVersion(this.childVersion1, rootVersion);
vh.addVersion(this.childVersion2, rootVersion);
return vh;
}
/**
* TODO Exception case - add version that has already been added
*/
/**
* TODO Exception case - add a version with a duplicate version label
*/
/**
* Test getPredecessor
*/
public void testGetPredecessor()
{
VersionHistoryImpl vh = testAddVersionImpl();
Version version1 = vh.getPredecessor(this.childVersion1);
assertEquals(version1.getVersionLabel(), this.rootVersion.getVersionLabel());
Version version2 = vh.getPredecessor(this.childVersion2);
assertEquals(version2.getVersionLabel(), this.rootVersion.getVersionLabel());
Version version3 = vh.getPredecessor(this.rootVersion);
assertNull(version3);
try
{
Version version4 = vh.getPredecessor(null);
assertNull(version4);
}
catch (Exception exception)
{
fail("Should continue by returning null.");
}
}
/**
* Test getSuccessors
*/
public void testGetSuccessors()
{
VersionHistoryImpl vh = testAddVersionImpl();
Collection<Version> versions1 = vh.getSuccessors(this.rootVersion);
assertNotNull(versions1);
assertEquals(versions1.size(), 2);
for (Version version : versions1)
{
String versionLabel = version.getVersionLabel();
if (!(versionLabel == "2" || versionLabel == "3"))
{
fail("There is a version in this collection that should not be here.");
}
}
Collection versions2 = vh.getSuccessors(this.childVersion1);
assertNotNull(versions2);
assertTrue(versions2.isEmpty());
Collection versions3 = vh.getSuccessors(this.childVersion2);
assertNotNull(versions3);
assertTrue(versions3.isEmpty());
}
/**
* Test getVersion
*/
public void testGetVersion()
{
VersionHistoryImpl vh = testAddVersionImpl();
Version version1 = vh.getVersion("1");
assertEquals(version1.getVersionLabel(), this.rootVersion.getVersionLabel());
Version version2 = vh.getVersion("2");
assertEquals(version2.getVersionLabel(), this.childVersion1.getVersionLabel());
Version version3 = vh.getVersion("3");
assertEquals(version3.getVersionLabel(), this.childVersion2.getVersionLabel());
try
{
vh.getVersion("invalidLabel");
fail("An exception should have been thrown if the version can not be retrieved.");
}
catch (VersionDoesNotExistException exception)
{
System.out.println("Error message: " + exception.getMessage());
}
}
}

View File

@@ -0,0 +1,197 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version.common;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.repository.datatype.TypeConverter;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionServiceException;
import org.alfresco.service.cmr.version.VersionType;
/**
* Version class implementation.
*
* Used to represent the data about a version stored in a version store.
*
* @author Roy Wetherall
*/
public class VersionImpl implements Version
{
/**
* Serial version UID
*/
private static final long serialVersionUID = 3257567304324888881L;
/**
* Error message(s)
*/
private static final String ERR_NO_NODE_REF = "A valid node reference must be supplied when creating a verison.";
/**
* The properties of the version
*/
private Map<String, Serializable> versionProperties = null;
/**
* The node reference that represents the frozen state of the versioned object
*/
private NodeRef nodeRef = null;
/**
* Constructor that initialises the state of the version object.
*
* @param versionProperties the version properties
* @param nodeRef the forzen state node reference
*/
public VersionImpl(
Map<String, Serializable> versionProperties,
NodeRef nodeRef)
{
if (nodeRef == null)
{
// Exception - a node ref must be specified
throw new VersionServiceException(VersionImpl.ERR_NO_NODE_REF);
}
this.versionProperties = versionProperties;
this.nodeRef = nodeRef;
}
/**
* Helper method to get the created date from the version property data.
*
* @return the date the version was created
*/
public Date getCreatedDate()
{
return (Date)this.versionProperties.get(VersionModel.PROP_CREATED_DATE);
}
public String getCreator()
{
return (String)this.versionProperties.get(VersionModel.PROP_CREATOR);
}
/**
* Helper method to get the version label from the version property data.
*
* @return the version label
*/
public String getVersionLabel()
{
return (String)this.versionProperties.get(VersionModel.PROP_VERSION_LABEL);
}
/**
* Helper method to get the version type.
*
* @return the value of the version type as an enum value
*/
public VersionType getVersionType()
{
return (VersionType)this.versionProperties.get(VersionModel.PROP_VERSION_TYPE);
}
/**
* Helper method to get the version description.
*
* @return the version description
*/
public String getDescription()
{
return (String)this.versionProperties.get(PROP_DESCRIPTION);
}
/**
* @see org.alfresco.service.cmr.version.Version#getVersionProperties()
*/
public Map<String, Serializable> getVersionProperties()
{
return this.versionProperties;
}
/**
* @see org.alfresco.service.cmr.version.Version#getVersionProperty(java.lang.String)
*/
public Serializable getVersionProperty(String name)
{
Serializable result = null;
if (this.versionProperties != null)
{
result = this.versionProperties.get(name);
}
return result;
}
/**
* @see org.alfresco.service.cmr.version.Version#getVersionedNodeRef()
*/
public NodeRef getVersionedNodeRef()
{
String storeProtocol = (String)this.versionProperties.get(VersionModel.PROP_FROZEN_NODE_STORE_PROTOCOL);
String storeId = (String)this.versionProperties.get(VersionModel.PROP_FROZEN_NODE_STORE_ID);
String nodeId = (String)this.versionProperties.get(VersionModel.PROP_FROZEN_NODE_ID);
return new NodeRef(new StoreRef(storeProtocol, storeId), nodeId);
}
/**
* @see org.alfresco.service.cmr.version.Version#getFrozenStateNodeRef()
*/
public NodeRef getFrozenStateNodeRef()
{
return this.nodeRef;
}
/**
* Static block to register the version type converters
*/
static
{
DefaultTypeConverter.INSTANCE.addConverter(
String.class,
VersionType.class,
new TypeConverter.Converter<String, VersionType>()
{
public VersionType convert(String source)
{
return VersionType.valueOf(source);
}
});
DefaultTypeConverter.INSTANCE.addConverter(
VersionType.class,
String.class,
new TypeConverter.Converter<VersionType, String>()
{
public String convert(VersionType source)
{
return source.toString();
}
});
}
}

View File

@@ -0,0 +1,188 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version.common;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionServiceException;
import org.alfresco.service.cmr.version.VersionType;
import junit.framework.TestCase;
/**
* VersionImpl Unit Test
*
* @author Roy Wetherall
*/
public class VersionImplTest extends TestCase
{
/**
* Property names and values
*/
private final static String PROP_1 = "prop1";
private final static String PROP_2 = "prop2";
private final static String PROP_3 = "prop3";
private final static String VALUE_1 = "value1";
private final static String VALUE_2 = "value2";
private final static String VALUE_3 = "value3";
private final static String VALUE_DESCRIPTION = "This string describes the version details.";
private final static VersionType VERSION_TYPE = VersionType.MINOR;
private final static String USER_NAME = "userName";
/**
* Version labels
*/
private final static String VERSION_1 = "1";
/**
* Data used during tests
*/
private VersionImpl version = null;
private NodeRef nodeRef = null;
private Map<String, Serializable> versionProperties = null;
private Date createdDate = new Date();
/**
* Test case set up
*/
protected void setUp() throws Exception
{
super.setUp();
// Create the node reference
this.nodeRef = new NodeRef(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "testWS"), "testID");
assertNotNull(this.nodeRef);
// Create the version property map
this.versionProperties = new HashMap<String, Serializable>();
this.versionProperties.put(VersionModel.PROP_VERSION_LABEL, VERSION_1);
this.versionProperties.put(VersionModel.PROP_CREATED_DATE, this.createdDate);
this.versionProperties.put(VersionModel.PROP_CREATOR, USER_NAME);
this.versionProperties.put(Version.PROP_DESCRIPTION, VALUE_DESCRIPTION);
this.versionProperties.put(VersionModel.PROP_VERSION_TYPE, VERSION_TYPE);
this.versionProperties.put(PROP_1, VALUE_1);
this.versionProperties.put(PROP_2, VALUE_2);
this.versionProperties.put(PROP_3, VALUE_3);
// Create the root version
this.version = new VersionImpl(this.versionProperties, this.nodeRef);
assertNotNull(this.version);
}
/**
* Test getCreatedDate()
*/
public void testGetCreatedDate()
{
Date createdDate1 = this.version.getCreatedDate();
assertEquals(this.createdDate, createdDate1);
}
/**
* Test getCreator
*/
public void testGetCreator()
{
assertEquals(USER_NAME, this.version.getCreator());
}
/**
* Test getVersionLabel()
*/
public void testGetVersionLabel()
{
String versionLabel1 = this.version.getVersionLabel();
assertEquals(VersionImplTest.VERSION_1, versionLabel1);
}
/**
* Test getDescription
*/
public void testGetDescription()
{
String description = this.version.getDescription();
assertEquals(VALUE_DESCRIPTION, description);
}
/**
* Test getVersionType
*/
public void testGetVersionType()
{
VersionType versionType = this.version.getVersionType();
assertEquals(VERSION_TYPE, versionType);
}
/**
* Test getVersionProperties
*
*/
public void testGetVersionProperties()
{
Map<String, Serializable> versionProperties = version.getVersionProperties();
assertNotNull(versionProperties);
assertEquals(this.versionProperties.size(), versionProperties.size());
}
/**
* Test getVersionProperty
*/
public void testGetVersionProperty()
{
String value1 = (String)version.getVersionProperty(VersionImplTest.PROP_1);
assertEquals(value1, VersionImplTest.VALUE_1);
String value2 = (String)version.getVersionProperty(VersionImplTest.PROP_2);
assertEquals(value2, VersionImplTest.VALUE_2);
String value3 = (String)version.getVersionProperty(VersionImplTest.PROP_3);
assertEquals(value3, VersionImplTest.VALUE_3);
}
/**
* Test getNodeRef()
*/
public void testGetNodeRef()
{
NodeRef nodeRef = this.version.getFrozenStateNodeRef();
assertNotNull(nodeRef);
assertEquals(nodeRef.toString(), this.nodeRef.toString());
}
/**
* Exception case - no node ref supplied when creating a verison
*/
public void testNoNodeRefOnVersionCreate()
{
try
{
new VersionImpl(this.versionProperties, null);
fail("It is invalid to create a version object without a node ref specified.");
}
catch (VersionServiceException exception)
{
}
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version.common;
import java.util.Collection;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.cmr.version.ReservedVersionNameException;
/**
* Helper class containing helper methods for the versioning services.
*
* @author Roy Wetherall
*/
public class VersionUtil
{
/**
* Reserved property names
*/
public static final String[] RESERVED_PROPERTY_NAMES = new String[]{
VersionModel.PROP_CREATED_DATE,
VersionModel.PROP_FROZEN_NODE_ID,
VersionModel.PROP_FROZEN_NODE_STORE_ID,
VersionModel.PROP_FROZEN_NODE_STORE_PROTOCOL,
VersionModel.PROP_FROZEN_NODE_TYPE,
VersionModel.PROP_FROZEN_ASPECTS,
VersionModel.PROP_VERSION_LABEL,
VersionModel.PROP_VERSION_NUMBER};
/**
* Checks that the names of the additional version properties are valid and that they do not clash
* with the reserved properties.
*
* @param versionProperties the property names
* @return true is the names are considered valid, false otherwise
* @throws ReservedVersionNameException
*/
public static void checkVersionPropertyNames(Collection<String> names)
throws ReservedVersionNameException
{
for (String name : RESERVED_PROPERTY_NAMES)
{
if (names.contains(name) == true)
{
throw new ReservedVersionNameException(name);
}
}
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version.common.counter;
import org.alfresco.service.cmr.repository.StoreRef;
/**
* Version counter DAO service interface.
*
* @author Roy Wetherall
*/
public interface VersionCounterDaoService
{
/**
* Get the next available version number for the specified store.
*
* @param storeRef the store reference
* @return the next version number
*/
public int nextVersionNumber(StoreRef storeRef);
/**
* Gets the current version number for the specified store.
*
* @param storeRef the store reference
* @return the current versio number
*/
public int currentVersionNumber(StoreRef storeRef);
/**
* Resets the version number for a the specified store.
*
* WARNING: calling this method will completely reset the current
* version count for the specified store and cannot be undone.
*
* @param storeRef the store reference
*/
public void resetVersionNumber(StoreRef storeRef);
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version.common.counter;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.util.BaseSpringTest;
/**
* @author Roy Wetherall
*/
public class VersionCounterDaoServiceTest extends BaseSpringTest
{
/*
* Test store id's
*/
private final static String STORE_ID_1 = "test1_" + System.currentTimeMillis();
private final static String STORE_ID_2 = "test2_" + System.currentTimeMillis();
private static final String STORE_NONE = "test3_" + System.currentTimeMillis();;
private NodeService nodeService;
private VersionCounterDaoService counter;
@Override
public void onSetUpInTransaction()
{
nodeService = (NodeService) applicationContext.getBean("dbNodeService");
counter = (VersionCounterDaoService) applicationContext.getBean("versionCounterDaoService");
}
public void testSetUp() throws Exception
{
assertNotNull(nodeService);
assertNotNull(counter);
}
/**
* Test nextVersionNumber
*/
public void testNextVersionNumber()
{
// Create the store references
StoreRef store1 = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, VersionCounterDaoServiceTest.STORE_ID_1);
StoreRef store2 = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, VersionCounterDaoServiceTest.STORE_ID_2);
StoreRef storeNone = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, VersionCounterDaoServiceTest.STORE_NONE);
int store1Version0 = this.counter.nextVersionNumber(store1);
assertEquals(store1Version0, 1);
int store1Version1 = this.counter.nextVersionNumber(store1);
assertEquals(store1Version1, 2);
int store2Version0 = this.counter.nextVersionNumber(store2);
assertEquals(store2Version0, 1);
int store1Version2 = this.counter.nextVersionNumber(store1);
assertEquals(store1Version2, 3);
int store2Version1 = this.counter.nextVersionNumber(store2);
assertEquals(store2Version1, 2);
int store1Current = this.counter.currentVersionNumber(store1);
assertEquals(store1Current, 3);
int store2Current = this.counter.currentVersionNumber(store2);
assertEquals(store2Current, 2);
int storeNoneCurrent = this.counter.currentVersionNumber(storeNone);
assertEquals(storeNoneCurrent, 0);
// Need to clean-up since the version counter works in its own transaction
this.counter.resetVersionNumber(store1);
this.counter.resetVersionNumber(store2);
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version.common.counter.hibernate;
import java.util.concurrent.locks.Lock;
import org.alfresco.repo.domain.StoreKey;
import org.alfresco.repo.domain.VersionCount;
import org.alfresco.repo.domain.hibernate.VersionCountImpl;
import org.alfresco.repo.version.common.counter.VersionCounterDaoService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
/**
* Version counter DAO service implemtation using Hibernate.
* <p>
* The object should execute within its own transaction, and is limited to single-thread
* entry. If it becomes a bottleneck, the transaction synchronization should be moved
* over to reentrant locks and/or the hibernate mappings should be optimized for better
* read-write access.
*
* @author Derek Hulley
*/
public class HibernateVersionCounterDaoServiceImpl extends HibernateDaoSupport implements VersionCounterDaoService
{
private Lock countReadLock;
private Lock countWriteLock;
/**
* Retrieves or creates a version counter
*
* @param storeKey
* @return Returns a current or new version counter
*/
private VersionCount getVersionCounter(StoreRef storeRef)
{
StoreKey storeKey = new StoreKey(storeRef.getProtocol(), storeRef.getIdentifier());
// get the version counter
VersionCount versionCounter = (VersionCount) getHibernateTemplate().get(VersionCountImpl.class, storeKey);
// check if it exists
if (versionCounter == null)
{
// create a new one
versionCounter = new VersionCountImpl();
getHibernateTemplate().save(versionCounter, storeKey);
}
return versionCounter;
}
/**
* Get the next available version number for the specified store.
*
* @param storeRef the version store id
* @return the next version number
*/
public synchronized int nextVersionNumber(StoreRef storeRef)
{
// get the version counter
VersionCount versionCounter = getVersionCounter(storeRef);
// get an incremented count
return versionCounter.incrementVersionCount();
}
/**
* Gets the current version number for the specified store.
*
* @param storeRef the store reference
* @return the current version number, zero if no version yet allocated.
*/
public synchronized int currentVersionNumber(StoreRef storeRef)
{
// get the version counter
VersionCount versionCounter = getVersionCounter(storeRef);
// get an incremented count
return versionCounter.getVersionCount();
}
/**
* Resets the version number for a the specified store.
*
* WARNING: calling this method will completely reset the current
* version count for the specified store and cannot be undone.
*
* @param storeRef the store reference
*/
public synchronized void resetVersionNumber(StoreRef storeRef)
{
// get the version counter
VersionCount versionCounter = getVersionCounter(storeRef);
// get an incremented count
versionCounter.resetVersionCount();
}
}

View File

@@ -0,0 +1,140 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version.common.versionlabel;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionType;
import org.alfresco.service.namespace.QName;
/**
* The serial version label policy.
*
* @author Roy Wetherall
*/
public class SerialVersionLabelPolicy
{
// TODO need to add support for branches into this labeling policy
/**
* Get the version label value base on the data provided.
*
* @param preceedingVersion the preceeding version, null if none
* @param versionNumber the new version number
* @param versionProperties the version property values
* @return the version label
*/
public String calculateVersionLabel(
QName classRef,
Version preceedingVersion,
int versionNumber,
Map<String, Serializable> versionProperties)
{
SerialVersionLabel serialVersionNumber = null;
if (preceedingVersion != null)
{
serialVersionNumber = new SerialVersionLabel(preceedingVersion.getVersionLabel());
VersionType versionType = (VersionType)versionProperties.get(VersionModel.PROP_VERSION_TYPE);
if (VersionType.MAJOR.equals(versionType) == true)
{
serialVersionNumber.majorIncrement();
}
else
{
serialVersionNumber.minorIncrement();
}
}
else
{
serialVersionNumber = new SerialVersionLabel(null);
}
return serialVersionNumber.toString();
}
/**
* Inner class encapsulating the notion of the serial version number.
*
* @author Roy Wetherall
*/
private class SerialVersionLabel
{
/**
* The version number delimiter
*/
private static final String DELIMITER = ".";
/**
* The major revision number
*/
private int majorRevisionNumber = 1;
/**
* The minor revision number
*/
private int minorRevisionNumber = 0;
/**
* Constructor
*
* @param version the vesion to take the version from
*/
public SerialVersionLabel(String versionLabel)
{
if (versionLabel != null && versionLabel.length() != 0)
{
int iIndex = versionLabel.indexOf(DELIMITER);
String majorString = versionLabel.substring(0, iIndex);
String minorString = versionLabel.substring(iIndex+1);
this.majorRevisionNumber = Integer.parseInt(majorString);
this.minorRevisionNumber = Integer.parseInt(minorString);
}
}
/**
* Increments the major revision numebr and sets the minor to
* zero.
*/
public void majorIncrement()
{
this.majorRevisionNumber += 1;
this.minorRevisionNumber = 0;
}
/**
* Increments only the minor revision number
*/
public void minorIncrement()
{
this.minorRevisionNumber += 1;
}
/**
* Converts the serial version number into a string
*/
public String toString()
{
return this.majorRevisionNumber + DELIMITER + this.minorRevisionNumber;
}
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.version.common.versionlabel;
import java.io.Serializable;
import java.util.HashMap;
import junit.framework.TestCase;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.repo.version.common.VersionImpl;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionType;
/**
* Unit test class for SerialVersionLabelPolicy class
*
* @author Roy Wetherall
*/
public class SerialVersionLabelPolicyTest extends TestCase
{
/**
* Test getVersionLabelValue
*/
public void testGetVersionLabelValue()
{
SerialVersionLabelPolicy policy = new SerialVersionLabelPolicy();
NodeRef dummyNodeRef = new NodeRef(new StoreRef("", ""), "");
HashMap<String, Serializable> versionProp1 = new HashMap<String, Serializable>();
versionProp1.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
String initialVersion = policy.calculateVersionLabel(
ContentModel.TYPE_CMOBJECT,
null,
0,
versionProp1);
assertEquals("1.0", initialVersion);
HashMap<String, Serializable> versionProp2 = new HashMap<String, Serializable>();
versionProp2.put(VersionModel.PROP_VERSION_LABEL, "1.0");
Version version1 = new VersionImpl(versionProp2, dummyNodeRef);
String verisonLabel1 = policy.calculateVersionLabel(
ContentModel.TYPE_CMOBJECT,
version1,
1,
versionProp1);
assertEquals("1.1", verisonLabel1);
HashMap<String, Serializable> versionProp3 = new HashMap<String, Serializable>();
versionProp3.put(VersionModel.PROP_VERSION_LABEL, "1.1");
Version version2 = new VersionImpl(versionProp3, dummyNodeRef);
HashMap<String, Serializable> versionProp4 = new HashMap<String, Serializable>();
versionProp4.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR);
String verisonLabel2 = policy.calculateVersionLabel(
ContentModel.TYPE_CMOBJECT,
version2,
1,
versionProp4);
assertEquals("2.0", verisonLabel2);
}
}

View File

@@ -0,0 +1,156 @@
<model name="ver:versionmodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
<description>Alfresco Version Store Model</description>
<author>Alfresco</author>
<published>2005-05-30</published>
<version>0.1</version>
<imports>
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
<import uri="http://www.alfresco.org/model/system/1.0" prefix="sys"/>
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
</imports>
<namespaces>
<namespace uri="http://www.alfresco.org/model/versionstore/1.0" prefix="ver"/>
</namespaces>
<types>
<type name="ver:versionMetaDataValue">
<parent>sys:base</parent>
<properties>
<property name="ver:metaDataName">
<type>d:text</type>
</property>
<property name="ver:metaDataValue">
<type>d:any</type>
</property>
</properties>
</type>
<type name="ver:versionedProperty">
<parent>sys:base</parent>
<properties>
<property name="ver:qname">
<type>d:qname</type>
</property>
<property name="ver:value">
<type>d:any</type>
</property>
<property name="ver:multiValue">
<type>d:any</type>
<multiple>true</multiple>
</property>
<property name="ver:isMultiValue">
<type>d:boolean</type>
</property>
</properties>
</type>
<type name="ver:versionedAssoc">
<parent>sys:reference</parent>
<properties>
<property name="ver:assocQName">
<type>d:qname</type>
</property>
</properties>
</type>
<type name="ver:versionedChildAssoc">
<parent>ver:versionedAssoc</parent>
<properties>
<property name="ver:isPrimary">
<type>d:boolean</type>
</property>
<property name="ver:nthSibling">
<type>d:int</type>
</property>
</properties>
</type>
<type name="ver:version">
<parent>sys:container</parent>
<properties>
<property name="ver:versionNumber">
<type>d:int</type>
</property>
<property name="ver:versionLabel">
<type>d:text</type>
</property>
<property name="ver:frozenNodeId">
<type>d:text</type>
</property>
<property name="ver:frozenNodeStoreId">
<type>d:text</type>
</property>
<property name="ver:frozenNodeStoreProtocol">
<type>d:text</type>
</property>
<property name="ver:frozenNodeType">
<type>d:qname</type>
</property>
<property name="ver:frozenAspects">
<type>d:qname</type>
<multiple>true</multiple>
</property>
</properties>
<associations>
<child-association name="ver:versionMetaData">
<target>
<class>ver:versionMetaDataValue</class>
</target>
</child-association>
<child-association name="ver:versionedAttributes">
<target>
<class>ver:versionedProperty</class>
</target>
</child-association>
<child-association name="ver:versionedChildAssocs">
<target>
<class>ver:versionedChildAssoc</class>
</target>
</child-association>
<child-association name="ver:versionedAssocs">
<target>
<class>ver:versionedAssoc</class>
</target>
</child-association>
<association name="ver:successor">
<target>
<class>ver:version</class>
</target>
</association>
</associations>
<mandatory-aspects>
<aspect>cm:auditable</aspect>
</mandatory-aspects>
</type>
<type name="ver:versionHistory">
<parent>sys:base</parent>
<properties>
<property name="ver:versionedNodeId">
<type>d:text</type>
</property>
</properties>
<associations>
<child-association name="ver:version">
<target>
<class>ver:version</class>
</target>
</child-association>
<association name="ver:rootVersion">
<target>
<class>ver:version</class>
</target>
</association>
</associations>
</type>
</types>
</model>