RM-1635: Recordable Version Store Service Prototype (WIP)

* extended version service implementation that can use the file plan as an alternative version store, thus recording versions
  * extended version node service implementation that can retrieve recorded version information from the file plan (rather than the version frozen state) (properties only atm)
  * recordable version model including recorded version information and versionable aspect extension with auto recordable version policy defined
  * Recordable version service unit tests
  * Simple AdHoc recorded version integration test (shows recorded created and frozen property state recovered via file plan record)



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@80223 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2014-08-15 06:02:38 +00:00
parent 3b73ae854f
commit 76671aedf4
28 changed files with 1304 additions and 22 deletions

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Recordable Version Model -->
<!-- -->
<!-- @since 2.3 -->
<!-- @author Roy Wetherall -->
<!-- Note: the rma: namespace is defined further on in the document -->
<model name="rmv:recordableVersion" xmlns="http://www.alfresco.org/model/dictionary/1.0">
<description>Recordable Version Model</description>
<author>Roy Wetherall</author>
<version>1.0</version>
<imports>
<!-- Import Alfresco Dictionary Definitions -->
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
<!-- Import Alfresco Content Domain Model Definitions -->
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
<!-- Import Alfresco Content Domain Model Definitions -->
<import uri="http://www.alfresco.org/model/system/1.0" prefix="sys" />
<!-- Import Alfresco Site Model Definitions -->
<import uri="http://www.alfresco.org/model/site/1.0" prefix="st"/>
<!-- Import Alfresco RM Model Definitions -->
<import uri="http://www.alfresco.org/model/recordsmanagement/1.0" prefix="rma"/>
</imports>
<namespaces>
<namespace uri="http://www.alfresco.org/model/recordableversion/1.0" prefix="rmv"/>
</namespaces>
<constraints>
<constraint name="rmv:recordableVersionPolicyList" type="LIST">
<title>Recordable Version Policy List</title>
<parameter name="allowedValues">
<list>
<value>NONE</value>
<value>MAJOR_ONLY</value>
<value>ALL</value>
</list>
</parameter>
<parameter name="caseSensitive"><value>false</value></parameter>
</constraint>
</constraints>
<aspects>
<aspect name="rmv:versionable">
<properties>
<property name="rmv:filePlan">
<title>File Plan</title>
<type>d:noderef</type>
<index enabled="false"/>
</property>
<property name="rmv:recordableVersionPolicy">
<title>Recordable Version Policy</title>
<type>d:text</type>
<default>disabled</default>
<index enabled="false"/>
<constraints>
<constraint ref="rmv:recordableVersionPolicyList" />
</constraints>
</property>
</properties>
</aspect>
<aspect name="rmv:recordedVersion">
<properties>
<property name="rmv:recordNodeRef">
<title>Record Node Reference</title>
<type>d:noderef</type>
<index enabled="false"/>
</property>
</properties>
</aspect>
</aspects>
</model>

View File

@@ -115,8 +115,11 @@
<!-- Import workflows --> <!-- Import workflows -->
<import resource="classpath:alfresco/module/org_alfresco_module_rm/rm-workflow-context.xml"/> <import resource="classpath:alfresco/module/org_alfresco_module_rm/rm-workflow-context.xml"/>
<!-- Import record service --> <!-- Import report service -->
<import resource="classpath:alfresco/module/org_alfresco_module_rm/rm-report-context.xml"/> <import resource="classpath:alfresco/module/org_alfresco_module_rm/rm-report-context.xml"/>
<!-- Import recordable version services -->
<import resource="classpath:alfresco/module/org_alfresco_module_rm/rm-version-context.xml"/>
<!-- RM Script API --> <!-- RM Script API -->

View File

@@ -0,0 +1,33 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<!-- Recordable Version Model -->
<bean id="org_alfresco_module_rm_version_dictionaryBootstrap" parent="dictionaryModelBootstrap">
<property name="models">
<list>
<value>alfresco/module/org_alfresco_module_rm/model/recordableVersionModel.xml</value>
</list>
</property>
</bean>
<!-- extended version service bean definition -->
<bean id="rm.versionService" abstract="true" class="org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionServiceImpl">
<property name="filePlanService" ref="FilePlanService" />
<property name="fileFolderService" ref="fileFolderService" />
</bean>
<bean class="org.alfresco.module.org_alfresco_module_rm.util.BeanExtender">
<property name="beanName" value="versionService" />
<property name="extendingBeanName" value="rm.versionService" />
</bean>
<!-- extended version node service bean definition -->
<bean id="rm.versionNodeService" abstract="true" class="org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionNodeServiceImpl">
</bean>
<bean class="org.alfresco.module.org_alfresco_module_rm.util.BeanExtender">
<property name="beanName" value="versionNodeService" />
<property name="extendingBeanName" value="rm.versionNodeService" />
</bean>
</beans>

View File

@@ -252,6 +252,12 @@
<version>0.1-incubating-unreleased</version> <version>0.1-incubating-unreleased</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-api</artifactId>
<version>2.1.9</version>
<scope>test</scope>
</dependency>
<!-- Database drivers --> <!-- Database drivers -->
<dependency> <dependency>
<groupId>postgresql</groupId> <groupId>postgresql</groupId>

View File

@@ -35,7 +35,6 @@ import net.sf.acegisecurity.ConfigAttributeDefinition;
import net.sf.acegisecurity.afterinvocation.AfterInvocationProvider; import net.sf.acegisecurity.afterinvocation.AfterInvocationProvider;
import net.sf.acegisecurity.vote.AccessDecisionVoter; import net.sf.acegisecurity.vote.AccessDecisionVoter;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.repo.search.SimpleResultSetMetaData; import org.alfresco.repo.search.SimpleResultSetMetaData;
import org.alfresco.repo.search.impl.lucene.PagingLuceneResultSet; import org.alfresco.repo.search.impl.lucene.PagingLuceneResultSet;
@@ -43,19 +42,17 @@ import org.alfresco.repo.search.impl.querymodel.QueryEngineResults;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.permissions.PermissionCheckCollection; import org.alfresco.repo.security.permissions.PermissionCheckCollection;
import org.alfresco.repo.security.permissions.PermissionCheckValue; import org.alfresco.repo.security.permissions.PermissionCheckValue;
import org.alfresco.repo.security.permissions.PermissionCheckedValue;
import org.alfresco.repo.security.permissions.PermissionCheckedCollection.PermissionCheckedCollectionMixin; import org.alfresco.repo.security.permissions.PermissionCheckedCollection.PermissionCheckedCollectionMixin;
import org.alfresco.repo.security.permissions.PermissionCheckedValue;
import org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterException; import org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterException;
import org.alfresco.repo.security.permissions.impl.acegi.FilteringResultSet; import org.alfresco.repo.security.permissions.impl.acegi.FilteringResultSet;
import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.search.LimitBy; import org.alfresco.service.cmr.search.LimitBy;
import org.alfresco.service.cmr.search.PermissionEvaluationMode; import org.alfresco.service.cmr.search.PermissionEvaluationMode;
import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.security.AccessStatus;
import org.aopalliance.intercept.MethodInvocation; import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.version;
import org.alfresco.service.namespace.QName;
/**
* Helper class containing recordable version model qualified names
*
* @author Roy Wetherall
* @since 2.3
*/
public interface RecordableVersionModel
{
/** Namespace details */
String RMV_URI = "http://www.alfresco.org/model/recordableversion/1.0";
String RMV_PREFIX = "rmv";
/** versionable aspect */
public QName ASPECT_VERSIONABLE = QName.createQName(RMV_URI, "versionable");
public QName PROP_RECORDABLE_VERSION_POLICY = QName.createQName(RMV_URI, "recordableVersionPolicy");
public QName PROP_FILE_PLAN = QName.createQName(RMV_URI, "filePlan");
/** recorded version aspect */
public QName ASPECT_RECORDED_VERSION = QName.createQName(RMV_URI, "recordedVersion");
public QName PROP_RECORD_NODE_REF = QName.createQName(RMV_URI, "recordNodeRef");
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.version;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.repo.version.Node2ServiceImpl;
import org.alfresco.repo.version.common.VersionUtil;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
/**
*
* @author Roy Wetherall
* @since 2.3
*/
public class RecordableVersionNodeServiceImpl extends Node2ServiceImpl
implements RecordableVersionModel
{
@Override
public Map<QName, Serializable> getProperties(NodeRef nodeRef) throws InvalidNodeRefException
{
NodeRef converted = VersionUtil.convertNodeRef(nodeRef);
if (dbNodeService.hasAspect(converted, ASPECT_RECORDED_VERSION))
{
NodeRef record = (NodeRef)dbNodeService.getProperty(converted, PROP_RECORD_NODE_REF);
Map<QName, Serializable> properties = dbNodeService.getProperties(record);
return processProperties(properties);
}
else
{
return super.getProperties(nodeRef);
}
}
protected Map<QName, Serializable> processProperties(Map<QName, Serializable> properties)
{
// revert modified record name
properties.put(ContentModel.PROP_NAME, properties.get(RecordsManagementModel.PROP_ORIGIONAL_NAME));
// remove all rma, rmc, rmr and rmv properties
// remove any properties relating to custom record-meta data
// do standard property processing
VersionUtil.convertFrozenToOriginalProps(properties);
return properties;
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.version;
/**
* @author Roy Wetherall
* @since 2.3
*/
public enum RecordableVersionPolicy
{
NONE,
MAJOR_ONLY,
ALL
}

View File

@@ -0,0 +1,334 @@
/*
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.version;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.repo.policy.PolicyScope;
import org.alfresco.repo.version.Version2Model;
import org.alfresco.repo.version.Version2ServiceImpl;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.ReservedVersionNameException;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionType;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Recordable version service implementation
*
* @author Roy Wetherall
* @since 2.3
*/
public class RecordableVersionServiceImpl extends Version2ServiceImpl
implements RecordableVersionModel
{
/** share logger with version2ServiceImpl */
private static Log logger = LogFactory.getLog(Version2ServiceImpl.class);
/** key used to indicate a recordable version */
public static final String KEY_RECORDABLE_VERSION = "recordable-version";
public static final String KEY_FILE_PLAN = "file-plan";
/** file plan service */
protected FilePlanService filePlanService;
/** file folder service */
protected FileFolderService fileFolderService;
/**
* @param filePlanService file plan service
*/
public void setFilePlanService(FilePlanService filePlanService)
{
this.filePlanService = filePlanService;
}
/**
* @param fileFolderService file folder service
*/
public void setFileFolderService(FileFolderService fileFolderService)
{
this.fileFolderService = fileFolderService;
}
/**
* @see org.alfresco.repo.version.Version2ServiceImpl#createVersion(org.alfresco.service.cmr.repository.NodeRef, java.util.Map, int)
*/
@Override
protected Version createVersion(NodeRef nodeRef, Map<String, Serializable> origVersionProperties, int versionNumber) throws ReservedVersionNameException
{
// TODO we only support recorded versions for sub types of cm:content
// create version properties if null
if (origVersionProperties == null)
{
origVersionProperties = new HashMap<String, Serializable>(2);
}
// only need to check the recordable version policy when the recordable version indicator is missing from the version properties
if (!origVersionProperties.containsKey(KEY_RECORDABLE_VERSION))
{
// get the version type
VersionType versionType = null;
if (origVersionProperties != null)
{
versionType = (VersionType)origVersionProperties.get(VersionModel.PROP_VERSION_TYPE);
}
// determine whether this is a recorded version or not
if (isCreateRecordedVersion(nodeRef, versionType))
{
origVersionProperties.put(KEY_RECORDABLE_VERSION, true);
if (!origVersionProperties.containsKey(KEY_FILE_PLAN))
{
// make sure the file plan is set to the default if not specified
origVersionProperties.put(KEY_FILE_PLAN, getFilePlan(nodeRef));
}
}
}
else
{
if (!origVersionProperties.containsKey(KEY_FILE_PLAN))
{
// make sure the file plan is set to the default if not specified
origVersionProperties.put(KEY_FILE_PLAN, getFilePlan(nodeRef));
}
}
return super.createVersion(nodeRef, origVersionProperties, versionNumber);
}
/**
*
* @param nodeRef
* @return
*/
private NodeRef getFilePlan(NodeRef nodeRef)
{
NodeRef filePlan = (NodeRef)nodeService.getProperty(nodeRef, PROP_FILE_PLAN);
if (filePlan == null)
{
filePlan = getFilePlan();
}
return filePlan;
}
/**
*
* @return
*/
private NodeRef getFilePlan()
{
NodeRef filePlan = filePlanService.getFilePlanBySiteId(FilePlanService.DEFAULT_RM_SITE_ID);
if (filePlan == null)
{
throw new AlfrescoRuntimeException("Can't create a recorded version, because there is no file plan.");
}
return filePlan;
}
/**
* Determine whether this is a recorded version or not.
*
* @param nodeRef
* @return
*/
private boolean isCreateRecordedVersion(NodeRef nodeRef, VersionType versionType)
{
boolean result = false;
if (nodeService.hasAspect(nodeRef, RecordableVersionModel.ASPECT_VERSIONABLE))
{
String policyString = (String)nodeService.getProperty(nodeRef, PROP_RECORDABLE_VERSION_POLICY);
if (policyString != null)
{
RecordableVersionPolicy policy = RecordableVersionPolicy.valueOf(policyString.toUpperCase());
if (RecordableVersionPolicy.ALL.equals(policy) ||
(RecordableVersionPolicy.MAJOR_ONLY.equals(policy) &&
VersionType.MAJOR.equals(versionType)))
{
result = true;
}
}
}
return result;
}
/**
* @see org.alfresco.repo.version.Version2ServiceImpl#createNewVersion(org.alfresco.service.namespace.QName, org.alfresco.service.cmr.repository.NodeRef, java.util.Map, java.util.Map, int, org.alfresco.repo.policy.PolicyScope)
*/
@Override
protected NodeRef createNewVersion( QName sourceTypeRef,
NodeRef versionHistoryRef,
Map<QName, Serializable> standardVersionProperties,
Map<String, Serializable> versionProperties,
int versionNumber,
PolicyScope nodeDetails)
{
NodeRef version = null;
if (versionProperties.containsKey(KEY_RECORDABLE_VERSION) &&
((Boolean)versionProperties.get(KEY_RECORDABLE_VERSION)).booleanValue())
{
// create a recorded version
version = createNewRecordedVersion(sourceTypeRef, versionHistoryRef, standardVersionProperties, versionProperties, versionNumber, nodeDetails);
}
else
{
// create a normal version
version = super.createNewVersion(sourceTypeRef, versionHistoryRef, standardVersionProperties, versionProperties, versionNumber, nodeDetails);
}
return version;
}
/**
*
* @param sourceTypeRef
* @param versionHistoryRef
* @param standardVersionProperties
* @param versionProperties
* @param versionNumber
* @param nodeDetails
* @return
*/
protected NodeRef createNewRecordedVersion(QName sourceTypeRef,
NodeRef versionHistoryRef,
Map<QName, Serializable> standardVersionProperties,
Map<String, Serializable> versionProperties,
int versionNumber,
PolicyScope nodeDetails)
{
NodeRef versionNodeRef = null;
// Disable auto-version behaviour
policyBehaviourFilter.disableBehaviour(ContentModel.ASPECT_VERSIONABLE);
// disable other behaviours that we don't want to trigger during this process
policyBehaviourFilter.disableBehaviour(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
policyBehaviourFilter.disableBehaviour(ContentModel.TYPE_MULTILINGUAL_CONTAINER);
try
{
// get the destination file plan
NodeRef filePlan = (NodeRef)versionProperties.get(KEY_FILE_PLAN);
if (filePlan == null)
{
throw new AlfrescoRuntimeException("Can't create a new recorded version, because no file plan has been specified in the version properties.");
}
// get the unfiled record folder
final NodeRef unfiledRecordFolder = filePlanService.getUnfiledContainer(filePlan);
// create a copy of the source node and place in the file plan
final NodeRef nodeRef = (NodeRef)standardVersionProperties.get(Version2Model.PROP_QNAME_FROZEN_NODE_REF);
// copy version state and create record
NodeRef record = null;
try
{
FileInfo recordInfo = fileFolderService.copy(nodeRef, unfiledRecordFolder, null);
record = recordInfo.getNodeRef();
}
catch (FileNotFoundException e)
{
throw new AlfrescoRuntimeException("Can't create recorded version, because copy fails.", e);
}
// set up extended permissions
// TODO
// create version nodeRef
ChildAssociationRef childAssocRef = this.dbNodeService.createNode(
versionHistoryRef,
Version2Model.CHILD_QNAME_VERSIONS,
QName.createQName(Version2Model.NAMESPACE_URI, Version2Model.CHILD_VERSIONS + "-" + versionNumber), // TODO - testing - note: all children (of a versioned node) will have the same version number, maybe replace with a version sequence of some sort 001-...00n
sourceTypeRef,
null);
versionNodeRef = childAssocRef.getChildRef();
// NOTE: special ML case - see also MultilingualContentServiceImpl.makeMLContainer
// if (sourceTypeRef.equals(ContentModel.TYPE_MULTILINGUAL_CONTAINER))
// {
// // Set the permissions to allow anything by anyone
// permissionService.setPermission(
// versionNodeRef,
// PermissionService.ALL_AUTHORITIES,
// PermissionService.ALL_PERMISSIONS, true);
// permissionService.setPermission(
// versionNodeRef,
// AuthenticationUtil.getGuestUserName(),
// PermissionService.ALL_PERMISSIONS, true);
// }
// add aspect with the standard version properties to the 'version' node
nodeService.addAspect(versionNodeRef, Version2Model.ASPECT_VERSION, standardVersionProperties);
// add the recordedVersion aspect with link to record
nodeService.addAspect(versionNodeRef, ASPECT_RECORDED_VERSION, Collections.singletonMap(PROP_RECORD_NODE_REF, (Serializable)record));
}
finally
{
// Enable behaviours
this.policyBehaviourFilter.enableBehaviour(ContentModel.ASPECT_VERSIONABLE);
this.policyBehaviourFilter.enableBehaviour(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
this.policyBehaviourFilter.enableBehaviour(ContentModel.TYPE_MULTILINGUAL_CONTAINER);
}
// If the auditable aspect is not there then add it to the 'version' node (after original aspects have been frozen)
if (dbNodeService.hasAspect(versionNodeRef, ContentModel.ASPECT_AUDITABLE) == false)
{
dbNodeService.addAspect(versionNodeRef, ContentModel.ASPECT_AUDITABLE, null);
}
if (logger.isTraceEnabled())
{
logger.trace("createNewRecordedVersion created (" + versionNumber + ") " + versionNodeRef);
}
return versionNodeRef;
}
@Override
protected Version getVersion(NodeRef versionRef)
{
Version version = super.getVersion(versionRef);
NodeRef record = (NodeRef)dbNodeService.getProperty(versionRef, PROP_RECORD_NODE_REF);
if (record != null)
{
version.getVersionProperties().put("RecordVersion", record);
}
return version;
}
}

View File

@@ -27,6 +27,7 @@ import org.alfresco.module.org_alfresco_module_rm.test.integration.job.JobTestSu
import org.alfresco.module.org_alfresco_module_rm.test.integration.record.RecordTestSuite; import org.alfresco.module.org_alfresco_module_rm.test.integration.record.RecordTestSuite;
import org.alfresco.module.org_alfresco_module_rm.test.integration.recordfolder.RecordFolderTestSuite; import org.alfresco.module.org_alfresco_module_rm.test.integration.recordfolder.RecordFolderTestSuite;
import org.alfresco.module.org_alfresco_module_rm.test.integration.report.ReportTestSuite; import org.alfresco.module.org_alfresco_module_rm.test.integration.report.ReportTestSuite;
import org.alfresco.module.org_alfresco_module_rm.test.integration.version.VersionTestSuite;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Suite; import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses; import org.junit.runners.Suite.SuiteClasses;
@@ -49,7 +50,8 @@ import org.junit.runners.Suite.SuiteClasses;
RecordTestSuite.class, RecordTestSuite.class,
RecordFolderTestSuite.class, RecordFolderTestSuite.class,
JobTestSuite.class, JobTestSuite.class,
HoldTestSuite.class HoldTestSuite.class,
VersionTestSuite.class
}) })
public class IntegrationTestSuite public class IntegrationTestSuite
{ {

View File

@@ -0,0 +1,114 @@
/*
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.test.integration.version;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionModel;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionServiceImpl;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionType;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.PropertyMap;
/**
*
*
* @author Roy Wetherall
* @since 2.3
*/
public class AdHocRecordableVersions extends BaseRMTestCase implements RecordableVersionModel
{
private static final QName QNAME_PUBLISHER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "publisher");
private static final QName QNAME_SUBJECT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "subject");
private static final String DESCRIPTION = "description";
private static final String PUBLISHER = "publisher";
private static final String SUBJECT = "subject";
@Override
protected boolean isCollaborationSiteTest()
{
return true;
}
public void testRecordAdHocVersionNoPolicy()
{
doBehaviourDrivenTest(new BehaviourDrivenTest()
{
private Version version;
private Map<String, Serializable> versionProperties;
public void given() throws Exception
{
// add Dublin core aspect
PropertyMap dublinCoreProperties = new PropertyMap(2);
dublinCoreProperties.put(QNAME_PUBLISHER, PUBLISHER);
dublinCoreProperties.put(QNAME_SUBJECT, SUBJECT);
nodeService.addAspect(documentLibrary, ContentModel.ASPECT_DUBLINCORE, dublinCoreProperties);
// setup version properties
versionProperties = new HashMap<String, Serializable>(4);
versionProperties.put(Version.PROP_DESCRIPTION, DESCRIPTION);
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
versionProperties.put(RecordableVersionServiceImpl.KEY_RECORDABLE_VERSION, true);
versionProperties.put(RecordableVersionServiceImpl.KEY_FILE_PLAN, filePlan);
}
public void when()
{
// create version
version = versionService.createVersion(dmDocument, versionProperties);
}
public void then()
{
// version has been created
assertNotNull(version);
// check the version properties
assertEquals(DESCRIPTION, version.getDescription());
assertEquals("0.1", version.getVersionLabel());
assertEquals(NAME_DM_DOCUMENT, nodeService.getProperty(dmDocument, ContentModel.PROP_NAME));
NodeRef frozen = version.getFrozenStateNodeRef();
assertEquals(NAME_DM_DOCUMENT, nodeService.getProperty(frozen, ContentModel.PROP_NAME));
// record version node reference is available on version
NodeRef record = (NodeRef)version.getVersionProperties().get("RecordVersion");
assertNotNull(record);
// record version is an unfiled record
assertTrue(recordService.isRecord(record));
assertFalse(recordService.isFiled(record));
}
});
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.test.integration.version;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
/**
* Recordable Version Test Suite
*
* @author Roy Wetherall
* @since 2.3
*/
@RunWith(Suite.class)
@SuiteClasses(
{
AdHocRecordableVersions.class
})
public class VersionTestSuite
{
}

View File

@@ -7,7 +7,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementActionService;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService; import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService;

View File

@@ -72,6 +72,7 @@ import org.alfresco.service.cmr.site.SiteInfo;
import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.cmr.site.SiteService;
import org.alfresco.service.cmr.site.SiteVisibility; import org.alfresco.service.cmr.site.SiteVisibility;
import org.alfresco.service.cmr.tagging.TaggingService; import org.alfresco.service.cmr.tagging.TaggingService;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService; import org.alfresco.service.transaction.TransactionService;
@@ -105,6 +106,9 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
protected QName TYPE_CUSTOM_TYPE = QName.createQName(URI, "customType"); protected QName TYPE_CUSTOM_TYPE = QName.createQName(URI, "customType");
protected QName ASPECT_CUSTOM_ASPECT = QName.createQName(URI, "customAspect"); protected QName ASPECT_CUSTOM_ASPECT = QName.createQName(URI, "customAspect");
protected QName ASPECT_RECORD_META_DATA = QName.createQName(URI, "recordMetaData"); protected QName ASPECT_RECORD_META_DATA = QName.createQName(URI, "recordMetaData");
/** test data */
protected String NAME_DM_DOCUMENT = "collabDocument.txt";
/** admin user */ /** admin user */
protected static final String ADMIN_USER = "admin"; protected static final String ADMIN_USER = "admin";
@@ -130,6 +134,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
protected TaggingService taggingService; protected TaggingService taggingService;
protected ActionService actionService; protected ActionService actionService;
protected OwnableService ownableService; protected OwnableService ownableService;
protected VersionService versionService;
/** RM Services */ /** RM Services */
protected DispositionService dispositionService; protected DispositionService dispositionService;
@@ -364,6 +369,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
taggingService = (TaggingService)applicationContext.getBean("TaggingService"); taggingService = (TaggingService)applicationContext.getBean("TaggingService");
actionService = (ActionService)applicationContext.getBean("ActionService"); actionService = (ActionService)applicationContext.getBean("ActionService");
ownableService = (OwnableService)applicationContext.getBean("OwnableService"); ownableService = (OwnableService)applicationContext.getBean("OwnableService");
versionService = (VersionService)applicationContext.getBean("VersionService");
// Get RM services // Get RM services
dispositionService = (DispositionService)applicationContext.getBean("DispositionService"); dispositionService = (DispositionService)applicationContext.getBean("DispositionService");
@@ -736,7 +742,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
// create a folder and documents // create a folder and documents
dmFolder = fileFolderService.create(documentLibrary, "collabFolder", ContentModel.TYPE_FOLDER).getNodeRef(); dmFolder = fileFolderService.create(documentLibrary, "collabFolder", ContentModel.TYPE_FOLDER).getNodeRef();
dmDocument = fileFolderService.create(dmFolder, "collabDocument.txt", ContentModel.TYPE_CONTENT).getNodeRef(); dmDocument = fileFolderService.create(dmFolder, NAME_DM_DOCUMENT, ContentModel.TYPE_CONTENT).getNodeRef();
dmConsumer = GUID.generate(); dmConsumer = GUID.generate();
dmConsumerNodeRef = createPerson(dmConsumer); dmConsumerNodeRef = createPerson(dmConsumer);

View File

@@ -51,7 +51,7 @@ public class FileReportActionUnitTest extends BaseUnitTest
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest#before() * @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest#before()
*/ */
@Override @Override
public void before() public void before() throws Exception
{ {
super.before(); super.before();

View File

@@ -67,7 +67,7 @@ public class HoldCapabilityConditionUnitTest extends BaseUnitTest
*/ */
@Before @Before
@Override @Override
public void before() public void before() throws Exception
{ {
super.before(); super.before();

View File

@@ -77,7 +77,7 @@ public class HoldServiceImplUnitTest extends BaseUnitTest
@Before @Before
@Override @Override
public void before() public void before() throws Exception
{ {
super.before(); super.before();

View File

@@ -72,7 +72,7 @@ public class DispositionLifecycleJobExecuterUnitTest extends BaseUnitTest
*/ */
@Override @Override
@Before @Before
public void before() public void before() throws Exception
{ {
super.before(); super.before();

View File

@@ -50,7 +50,7 @@ public class FrozenEvaluatorUnitTest extends BaseUnitTest
@Before @Before
@Override @Override
public void before() public void before() throws Exception
{ {
super.before(); super.before();

View File

@@ -51,7 +51,7 @@ public class TransferEvaluatorUnitTest extends BaseUnitTest
@Spy @InjectMocks TransferEvaluator transferEvaluator; @Spy @InjectMocks TransferEvaluator transferEvaluator;
@Override @Override
public void before() public void before() throws Exception
{ {
super.before(); super.before();

View File

@@ -55,7 +55,7 @@ public class RecordServiceImplUnitTest extends BaseUnitTest
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Before @Before
@Override @Override
public void before() public void before() throws Exception
{ {
super.before(); super.before();

View File

@@ -27,7 +27,7 @@ public abstract class BaseHoldWebScriptUnitTest extends BaseWebScriptUnitTest
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest#before() * @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest#before()
*/ */
@Override @Override
public void before() public void before() throws Exception
{ {
super.before(); super.before();

View File

@@ -83,7 +83,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest#before() * @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest#before()
*/ */
@Override @Override
public void before() public void before() throws Exception
{ {
super.before(); super.before();

View File

@@ -32,7 +32,9 @@ import org.alfresco.module.org_alfresco_module_rm.record.RecordServiceImplUnitTe
import org.alfresco.module.org_alfresco_module_rm.script.hold.HoldPostUnitTest; import org.alfresco.module.org_alfresco_module_rm.script.hold.HoldPostUnitTest;
import org.alfresco.module.org_alfresco_module_rm.script.hold.HoldPutUnitTest; import org.alfresco.module.org_alfresco_module_rm.script.hold.HoldPutUnitTest;
import org.alfresco.module.org_alfresco_module_rm.script.hold.HoldsGetUnitTest; import org.alfresco.module.org_alfresco_module_rm.script.hold.HoldsGetUnitTest;
import org.alfresco.module.org_alfresco_module_rm.security.FilePlanPermissionServiceImplUnitTest;
import org.alfresco.module.org_alfresco_module_rm.util.BeanExtenderUnitTest; import org.alfresco.module.org_alfresco_module_rm.util.BeanExtenderUnitTest;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionServiceImplUnitTest;
import org.alfresco.repo.action.parameter.DateParameterProcessorUnitTest; import org.alfresco.repo.action.parameter.DateParameterProcessorUnitTest;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Suite; import org.junit.runners.Suite;
@@ -57,7 +59,8 @@ import org.junit.runners.Suite.SuiteClasses;
// services // services
RecordServiceImplUnitTest.class, RecordServiceImplUnitTest.class,
HoldServiceImplUnitTest.class, HoldServiceImplUnitTest.class,
//FilePlanPermissionServiceImplUnitTest.class, FilePlanPermissionServiceImplUnitTest.class,
RecordableVersionServiceImplUnitTest.class,
// evaluators // evaluators
TransferEvaluatorUnitTest.class, TransferEvaluatorUnitTest.class,

View File

@@ -23,6 +23,7 @@ import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.util.ArrayList; import java.util.ArrayList;
@@ -41,11 +42,15 @@ import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderServi
import org.alfresco.module.org_alfresco_module_rm.report.ReportService; import org.alfresco.module.org_alfresco_module_rm.report.ReportService;
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService; import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl; import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.CopyService;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.repository.StoreRef;
@@ -77,7 +82,7 @@ import org.springframework.context.ApplicationContext;
* @author Roy Wetherall * @author Roy Wetherall
* @since 2.2 * @since 2.2
*/ */
public class BaseUnitTest implements RecordsManagementModel public class BaseUnitTest implements RecordsManagementModel, ContentModel
{ {
protected NodeRef filePlanComponent; protected NodeRef filePlanComponent;
protected NodeRef filePlan; protected NodeRef filePlan;
@@ -95,6 +100,9 @@ public class BaseUnitTest implements RecordsManagementModel
@Mock(name="searchService") protected SearchService mockedSearchService; @Mock(name="searchService") protected SearchService mockedSearchService;
@Mock(name="retryingTransactionHelper") protected RetryingTransactionHelper mockedRetryingTransactionHelper; @Mock(name="retryingTransactionHelper") protected RetryingTransactionHelper mockedRetryingTransactionHelper;
@Mock(name="authorityService") protected AuthorityService mockedAuthorityService; @Mock(name="authorityService") protected AuthorityService mockedAuthorityService;
@Mock(name="policyComponent") protected PolicyComponent mockedPolicyComponent;
@Mock(name="copyService") protected CopyService mockedCopyService;
@Mock(name="fileFolderService") protected FileFolderService mockedFileFolderService;
/** rm service mocks */ /** rm service mocks */
@Mock(name="filePlanService") protected FilePlanService mockedFilePlanService; @Mock(name="filePlanService") protected FilePlanService mockedFilePlanService;
@@ -105,6 +113,7 @@ public class BaseUnitTest implements RecordsManagementModel
@Mock(name="reportService") protected ReportService mockedReportService; @Mock(name="reportService") protected ReportService mockedReportService;
@Mock(name="filePlanRoleService") protected FilePlanRoleService mockedFilePlanRoleService; @Mock(name="filePlanRoleService") protected FilePlanRoleService mockedFilePlanRoleService;
@Mock(name="recordsManagementAuditService") protected RecordsManagementAuditService mockedRecordsManagementAuditService; @Mock(name="recordsManagementAuditService") protected RecordsManagementAuditService mockedRecordsManagementAuditService;
@Mock(name="policyBehaviourFilter") protected BehaviourFilter mockedBehaviourFilter;
/** application context mock */ /** application context mock */
@Mock(name="applicationContext") protected ApplicationContext mockedApplicationContext; @Mock(name="applicationContext") protected ApplicationContext mockedApplicationContext;
@@ -118,7 +127,7 @@ public class BaseUnitTest implements RecordsManagementModel
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Before @Before
public void before() public void before() throws Exception
{ {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
@@ -161,7 +170,7 @@ public class BaseUnitTest implements RecordsManagementModel
doReturn(result).when(mockedNodeService).getChildAssocs(eq(recordFolder), eq(ContentModel.ASSOC_CONTAINS), any(QNamePattern.class)); doReturn(result).when(mockedNodeService).getChildAssocs(eq(recordFolder), eq(ContentModel.ASSOC_CONTAINS), any(QNamePattern.class));
doReturn(result).when(mockedNodeService).getParentAssocs(record); doReturn(result).when(mockedNodeService).getParentAssocs(record);
doReturn(Collections.singletonList(recordFolder)).when(mockedRecordFolderService).getRecordFolders(record); doReturn(Collections.singletonList(recordFolder)).when(mockedRecordFolderService).getRecordFolders(record);
doReturn(Collections.singletonList(record)).when(mockedRecordService).getRecords(recordFolder); doReturn(Collections.singletonList(record)).when(mockedRecordService).getRecords(recordFolder);
} }
/** /**
@@ -250,6 +259,19 @@ public class BaseUnitTest implements RecordsManagementModel
return generateNodeRef(type, true); return generateNodeRef(type, true);
} }
/**
* Helper method to generate a cm:content node reference with a given name.
*
* @param name content name
* @return NodeRef node reference
*/
protected NodeRef generateCmContent(String name)
{
NodeRef nodeRef = generateNodeRef(ContentModel.TYPE_CONTENT, true);
doReturn(name).when(mockedNodeService).getProperty(nodeRef, ContentModel.PROP_NAME);
return nodeRef;
}
/** /**
* Helper method to generate a node reference of a particular type with a given existence characteristic. * Helper method to generate a node reference of a particular type with a given existence characteristic.
* *
@@ -268,6 +290,30 @@ public class BaseUnitTest implements RecordsManagementModel
} }
return nodeRef; return nodeRef;
} }
/**
* Helper method to generate a mocked child association reference.
*
* @param parent parent node (optional)
* @param child child node (optional)
* @return {@link ChildAssociationRef} mocked to return the parent and child nodes
*/
protected ChildAssociationRef generateChildAssociationRef(NodeRef parent, NodeRef child)
{
ChildAssociationRef mockedChildAssociationRef = mock(ChildAssociationRef.class);
if (parent != null)
{
doReturn(parent).when(mockedChildAssociationRef).getParentRef();
}
if (child != null)
{
doReturn(child).when(mockedChildAssociationRef).getChildRef();
}
return mockedChildAssociationRef;
}
/** /**
* Helper method to make one node the primary parent of the other. * Helper method to make one node the primary parent of the other.

View File

@@ -61,7 +61,7 @@ public class BeanExtenderUnitTest extends BaseUnitTest
@InjectMocks private BeanExtender beanExtender; @InjectMocks private BeanExtender beanExtender;
@Override @Override
public void before() public void before() throws Exception
{ {
super.before(); super.before();

View File

@@ -0,0 +1,416 @@
/*
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.version;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyMap;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.anyString;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest;
import org.alfresco.repo.version.Version2Model;
import org.alfresco.repo.version.VersionMigrator;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.version.VersionType;
import org.alfresco.service.namespace.QName;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
/**
* Recordable version service implementation unit test.
*
* @author Roy Wetherall
* @since 2.3
*/
public class RecordableVersionServiceImplUnitTest extends BaseUnitTest
{
/** versioned content name */
private static final String CONTENT_NAME = "test.txt";
/** versioned node reference */
private NodeRef nodeRef;
private NodeRef record;
private NodeRef unfiledRecordContainer;
private NodeRef version;
/** mocked version properties */
private Map<String, Serializable> versionProperties;
/** mocked services */
private @Mock(name="versionMigrator") VersionMigrator mockedVersionMigrator;
private @Mock(name="dbNodeService") NodeService mockedDbNodeService;
/** recordable version service */
private @InjectMocks TestRecordableVersionServiceImpl recordableVersionService;
/**
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest#before()
*/
@SuppressWarnings("unchecked")
@Override
public void before() throws Exception
{
super.before();
nodeRef = generateCmContent(CONTENT_NAME);
doReturn(123l).when(mockedNodeService).getProperty(nodeRef, ContentModel.PROP_NODE_DBID);
versionProperties = new HashMap<String, Serializable>(5);
recordableVersionService.initialise();
doReturn(generateChildAssociationRef(null, generateNodeRef(Version2Model.TYPE_QNAME_VERSION_HISTORY)))
.when(mockedDbNodeService).createNode(any(NodeRef.class),
any(QName.class),
any(QName.class),
eq(Version2Model.TYPE_QNAME_VERSION_HISTORY),
anyMap());
doReturn(generateChildAssociationRef(null, generateNodeRef(TYPE_CONTENT)))
.when(mockedDbNodeService).createNode(any(NodeRef.class),
any(QName.class),
any(QName.class),
eq(TYPE_CONTENT),
anyMap());
doReturn(filePlan).when(mockedFilePlanService).getFilePlanBySiteId(FilePlanService.DEFAULT_RM_SITE_ID);
doReturn(unfiledRecordContainer).when(mockedFilePlanService).getUnfiledContainer(any(NodeRef.class));
record = generateCmContent(CONTENT_NAME);
FileInfo mockedFileInfo = mock(FileInfo.class);
doReturn(record).when(mockedFileInfo).getNodeRef();
doReturn(mockedFileInfo).when(mockedFileFolderService).copy(any(NodeRef.class),
any(NodeRef.class),
any(String.class));
version = generateNodeRef(TYPE_CONTENT);
doReturn(generateChildAssociationRef(null, version)).when(mockedDbNodeService).createNode(
any(NodeRef.class),
eq(Version2Model.CHILD_QNAME_VERSIONS),
any(QName.class),
eq(TYPE_CONTENT),
anyMap());
}
/**
* Given that the node has no recordable version aspect
* When I create a version
* Then version service creates a normal version.
*/
@Test
public void noAspect() throws Exception
{
// setup given conditions
doReturn(false).when(mockedNodeService).hasAspect(nodeRef, RecordableVersionModel.ASPECT_VERSIONABLE);
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
// when version is created
recordableVersionService.createVersion(nodeRef, versionProperties);
// then a normal version is created
verifyNormalVersion();
}
/**
* Given that the node has a recordable version policy of null
* When I create a version
* Then the version service creates a normal version.
*/
@Test
public void policyNull() throws Exception
{
// setup given conditions
doReturn(false).when(mockedNodeService).hasAspect(nodeRef, RecordableVersionModel.ASPECT_VERSIONABLE);
doReturn(null).when(mockedNodeService).getProperty(nodeRef, RecordableVersionModel.PROP_RECORDABLE_VERSION_POLICY);
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
// when version is created
recordableVersionService.createVersion(nodeRef, versionProperties);
// then a normal version is created
verifyNormalVersion();
}
/**
* Given that the node has a recordable version policy of NONE
* When I create a version
* Then the version service creates a normal version.
*/
@Test
public void policyNone() throws Exception
{
// setup given conditions
doReturn(true).when(mockedNodeService).hasAspect(nodeRef, RecordableVersionModel.ASPECT_VERSIONABLE);
doReturn(RecordableVersionPolicy.NONE.toString()).when(mockedNodeService).getProperty(nodeRef, RecordableVersionModel.PROP_RECORDABLE_VERSION_POLICY);
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
// when version is created
recordableVersionService.createVersion(nodeRef, versionProperties);
// then a normal version is created
verifyNormalVersion();
}
/**
* Given that the node has a recordable version policy of ALL
* When I create a MINOR version then
* the version service creates a recorded version
*/
@Test
public void policyAllVersionMinor() throws Exception
{
// setup given conditions
doReturn(true).when(mockedNodeService).hasAspect(nodeRef, RecordableVersionModel.ASPECT_VERSIONABLE);
doReturn(RecordableVersionPolicy.ALL.toString()).when(mockedNodeService).getProperty(nodeRef, RecordableVersionModel.PROP_RECORDABLE_VERSION_POLICY);
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
// when version is created
recordableVersionService.createVersion(nodeRef, versionProperties);
// then the recorded version is created
verifyRecordedVersion(filePlan);
}
/**
* Helper method that verifies that a recorded version was created.
*/
@SuppressWarnings("unchecked")
private void verifyRecordedVersion(NodeRef filePlan) throws Exception
{
// then unfiled container is retrieved for file plan
verify(mockedFilePlanService, times(1)).getUnfiledContainer(filePlan);
// then the node is copied into the file plan
verify(mockedFileFolderService, times(1)).copy(eq(nodeRef),
eq(unfiledRecordContainer),
anyString());
// then the version is created
verify(mockedDbNodeService, times(1)).createNode(any(NodeRef.class),
eq(Version2Model.CHILD_QNAME_VERSIONS),
any(QName.class),
eq(TYPE_CONTENT),
anyMap());
verify(mockedNodeService, times(1)).addAspect(eq(version), eq(Version2Model.ASPECT_VERSION), anyMap());
verify(mockedNodeService, times(1)).addAspect(eq(version), eq(RecordableVersionModel.ASPECT_RECORDED_VERSION),
eq(Collections.singletonMap(RecordableVersionModel.PROP_RECORD_NODE_REF, (Serializable)record)));
}
/**
* Helper method that verified that a recorded version was not created.
*/
@SuppressWarnings("unchecked")
private void verifyNormalVersion() throws Exception
{
// verify no interactions
verify(mockedFilePlanService, never()).getUnfiledContainer(any(NodeRef.class));
verify(mockedFileFolderService, never()).copy(eq(nodeRef),
eq(unfiledRecordContainer),
anyString());
// then the version is created
verify(mockedDbNodeService, times(1)).createNode(any(NodeRef.class),
eq(Version2Model.CHILD_QNAME_VERSIONS),
any(QName.class),
eq(TYPE_CONTENT),
anyMap());
verify(mockedNodeService, times(1)).addAspect(eq(version), eq(Version2Model.ASPECT_VERSION), anyMap());
verify(mockedNodeService, never()).addAspect(eq(version), eq(RecordableVersionModel.PROP_RECORD_NODE_REF), anyMap());
}
/**
* Given that the node has a recordable version policy of ALL
* When I create a MAJOR version then
* the version service creates a recorded version
*/
@Test
public void policyAllVersionMajor() throws Exception
{
// setup given conditions
doReturn(true).when(mockedNodeService).hasAspect(nodeRef, RecordableVersionModel.ASPECT_VERSIONABLE);
doReturn(RecordableVersionPolicy.ALL.toString()).when(mockedNodeService).getProperty(nodeRef, RecordableVersionModel.PROP_RECORDABLE_VERSION_POLICY);
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR);
// when version is created
recordableVersionService.createVersion(nodeRef, versionProperties);
// then the recorded version is created
verifyRecordedVersion(filePlan);
}
/**
* Given that the node has a recordable version policy of MAJOR_ONLY
* When I create a MINOR version then
* the version service creates a normal version
*/
@Test
public void policyMajorOnlyVersionMinor() throws Exception
{
// setup given conditions
doReturn(true).when(mockedNodeService).hasAspect(nodeRef, RecordableVersionModel.ASPECT_VERSIONABLE);
doReturn(RecordableVersionPolicy.MAJOR_ONLY.toString()).when(mockedNodeService).getProperty(nodeRef, RecordableVersionModel.PROP_RECORDABLE_VERSION_POLICY);
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
// when version is created
recordableVersionService.createVersion(nodeRef, versionProperties);
// then a normal version is created
verifyNormalVersion();
}
/**
* Given that the node has a recordable version policy of MAJOR_ONLY
* When I create a MAJOR version then
* the version service creates a recorded version
*/
@Test
public void policyMajorOnlyVersionMajor() throws Exception
{
// setup given conditions
doReturn(true).when(mockedNodeService).hasAspect(nodeRef, RecordableVersionModel.ASPECT_VERSIONABLE);
doReturn(RecordableVersionPolicy.MAJOR_ONLY.toString()).when(mockedNodeService).getProperty(nodeRef, RecordableVersionModel.PROP_RECORDABLE_VERSION_POLICY);
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR);
// when version is created
recordableVersionService.createVersion(nodeRef, versionProperties);
// then the recorded version is created
verifyRecordedVersion(filePlan);
}
/**
* Given that the node has a valid recordable version policy
* And there is no file plan
* When I create a new version
* Then an exception should be thrown to indicate that there is no file plan
*/
@Test
public void noFilePlan() throws Exception
{
// setup given conditions
doReturn(true).when(mockedNodeService).hasAspect(nodeRef, RecordableVersionModel.ASPECT_VERSIONABLE);
doReturn(RecordableVersionPolicy.MAJOR_ONLY.toString()).when(mockedNodeService).getProperty(nodeRef, RecordableVersionModel.PROP_RECORDABLE_VERSION_POLICY);
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR);
doReturn(null).when(mockedFilePlanService).getFilePlanBySiteId(FilePlanService.DEFAULT_RM_SITE_ID);
// expected exception
exception.expect(AlfrescoRuntimeException.class);
// when version is created
recordableVersionService.createVersion(nodeRef, versionProperties);
}
/**
* Given that the node has a valid recordable version policy
* And that I set a specific file plan in the version properties
* When I create a new version
* Then the recorded version should be directed to the specified file plan, not the default file plan
*/
@Test
public void filePlanSpecifiedWithPolicy() throws Exception
{
// setup given conditions
doReturn(true).when(mockedNodeService).hasAspect(nodeRef, RecordableVersionModel.ASPECT_VERSIONABLE);
doReturn(RecordableVersionPolicy.MAJOR_ONLY.toString()).when(mockedNodeService).getProperty(nodeRef, RecordableVersionModel.PROP_RECORDABLE_VERSION_POLICY);
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR);
// specify the file plan
NodeRef anotherFilePlan = generateNodeRef(TYPE_FILE_PLAN);
versionProperties.put(RecordableVersionServiceImpl.KEY_FILE_PLAN, anotherFilePlan);
// when version is created
recordableVersionService.createVersion(nodeRef, versionProperties);
// then the recorded version is created
verifyRecordedVersion(anotherFilePlan);
}
/**
* Given that the node has specifically indicated that a recorded version should be created
* And that I set a specific file plan in the version properties
* When I create a new version
* Then the recorded version should be directed to the specified file plan, not the default file plan
*/
@Test
public void filePlanSpecifiedNoPolicy() throws Exception
{
// setup given conditions
doReturn(true).when(mockedNodeService).hasAspect(nodeRef, RecordableVersionModel.ASPECT_VERSIONABLE);
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR);
versionProperties.put(RecordableVersionServiceImpl.KEY_RECORDABLE_VERSION, true);
// specify the file plan
NodeRef anotherFilePlan = generateNodeRef(TYPE_FILE_PLAN);
versionProperties.put(RecordableVersionServiceImpl.KEY_FILE_PLAN, anotherFilePlan);
// when version is created
recordableVersionService.createVersion(nodeRef, versionProperties);
// then the recorded version is created
verifyRecordedVersion(anotherFilePlan);
}
@Test
public void adHocRecordedVersionNoPolicy() throws Exception
{
// setup given conditions
doReturn(true).when(mockedNodeService).hasAspect(nodeRef, RecordableVersionModel.ASPECT_VERSIONABLE);
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR);
versionProperties.put(RecordableVersionServiceImpl.KEY_RECORDABLE_VERSION, true);
// when version is created
recordableVersionService.createVersion(nodeRef, versionProperties);
// then the recorded version is created
verifyRecordedVersion(filePlan);
}
@Test
public void adHocRecordedVersionOverridePolicy() throws Exception
{
// setup given conditions
doReturn(true).when(mockedNodeService).hasAspect(nodeRef, RecordableVersionModel.ASPECT_VERSIONABLE);
doReturn(RecordableVersionPolicy.MAJOR_ONLY.toString()).when(mockedNodeService).getProperty(nodeRef, RecordableVersionModel.PROP_RECORDABLE_VERSION_POLICY);
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
versionProperties.put(RecordableVersionServiceImpl.KEY_RECORDABLE_VERSION, true);
// when version is created
recordableVersionService.createVersion(nodeRef, versionProperties);
// then the recorded version is created
verifyRecordedVersion(filePlan);
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.version;
import java.io.Serializable;
import java.util.Map;
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;
/**
* Helper class to help with the unit testing of RecordableVersionServiceImpl.
*
* @author Roy Wetherall
* @since 2.3
*/
public class TestRecordableVersionServiceImpl extends RecordableVersionServiceImpl
{
@Override
protected void invokeBeforeCreateVersion(NodeRef nodeRef)
{
}
@Override
protected void invokeAfterCreateVersion(NodeRef nodeRef, Version version)
{
}
@Override
protected void invokeAfterVersionRevert(NodeRef nodeRef, Version version)
{
}
@Override
protected void invokeOnCreateVersion(NodeRef nodeRef, Map<String, Serializable> versionProperties,PolicyScope nodeDetails)
{
}
@Override
protected String invokeCalculateVersionLabel(QName classRef, Version preceedingVersion, int versionNumber, Map<String, Serializable> versionProperties)
{
return "1.1";
}
}