diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordableVersionModel.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordableVersionModel.xml new file mode 100644 index 0000000000..f6fa3fb753 --- /dev/null +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordableVersionModel.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + Recordable Version Model + Roy Wetherall + 1.0 + + + + + + + + + + + + + + + + + + + + + Recordable Version Policy List + + + NONE + MAJOR_ONLY + ALL + + + false + + + + + + + + + File Plan + d:noderef + + + + Recordable Version Policy + d:text + disabled + + + + + + + + + + + + Record Node Reference + d:noderef + + + + + + + + \ No newline at end of file diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml index 1b1674c29f..68681e812d 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml @@ -115,8 +115,11 @@ - + + + + diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-version-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-version-context.xml new file mode 100644 index 0000000000..b21756a61d --- /dev/null +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-version-context.xml @@ -0,0 +1,33 @@ + + + + + + + + + + alfresco/module/org_alfresco_module_rm/model/recordableVersionModel.xml + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rm-server/pom.xml b/rm-server/pom.xml index ab7e505930..c51ee08fda 100644 --- a/rm-server/pom.xml +++ b/rm-server/pom.xml @@ -252,6 +252,12 @@ 0.1-incubating-unreleased test + + org.apache.myfaces.core + myfaces-api + 2.1.9 + test + postgresql diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMAfterInvocationProvider.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMAfterInvocationProvider.java index ea88be3e7d..b16c065f2a 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMAfterInvocationProvider.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMAfterInvocationProvider.java @@ -35,7 +35,6 @@ import net.sf.acegisecurity.ConfigAttributeDefinition; import net.sf.acegisecurity.afterinvocation.AfterInvocationProvider; import net.sf.acegisecurity.vote.AccessDecisionVoter; -import org.alfresco.model.ContentModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.repo.search.SimpleResultSetMetaData; 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.permissions.PermissionCheckCollection; 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.PermissionCheckedValue; import org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterException; import org.alfresco.repo.security.permissions.impl.acegi.FilteringResultSet; 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.StoreRef; -import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.search.LimitBy; import org.alfresco.service.cmr.search.PermissionEvaluationMode; import org.alfresco.service.cmr.search.ResultSet; -import org.alfresco.service.cmr.security.AccessStatus; import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionModel.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionModel.java new file mode 100644 index 0000000000..7f5f6389aa --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionModel.java @@ -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 . + */ +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"); +} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionNodeServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionNodeServiceImpl.java new file mode 100644 index 0000000000..9809bd12c3 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionNodeServiceImpl.java @@ -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 . + */ +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 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 properties = dbNodeService.getProperties(record); + return processProperties(properties); + } + else + { + return super.getProperties(nodeRef); + } + } + + protected Map processProperties(Map 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; + } +} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionPolicy.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionPolicy.java new file mode 100644 index 0000000000..ec730d4909 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionPolicy.java @@ -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 . + */ +package org.alfresco.module.org_alfresco_module_rm.version; + +/** + * @author Roy Wetherall + * @since 2.3 + */ +public enum RecordableVersionPolicy +{ + NONE, + MAJOR_ONLY, + ALL +} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionServiceImpl.java new file mode 100644 index 0000000000..42860a9d01 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionServiceImpl.java @@ -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 . + */ +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 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(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 standardVersionProperties, + Map 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 standardVersionProperties, + Map 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; + } +} diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/IntegrationTestSuite.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/IntegrationTestSuite.java index 23b3469a87..0a675eb2b8 100755 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/IntegrationTestSuite.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/IntegrationTestSuite.java @@ -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.recordfolder.RecordFolderTestSuite; 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.runners.Suite; import org.junit.runners.Suite.SuiteClasses; @@ -49,7 +50,8 @@ import org.junit.runners.Suite.SuiteClasses; RecordTestSuite.class, RecordFolderTestSuite.class, JobTestSuite.class, - HoldTestSuite.class + HoldTestSuite.class, + VersionTestSuite.class }) public class IntegrationTestSuite { diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/AdHocRecordableVersions.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/AdHocRecordableVersions.java new file mode 100644 index 0000000000..b7a0df85c1 --- /dev/null +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/AdHocRecordableVersions.java @@ -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 . + */ +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 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(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)); + } + }); + + } + +} diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/VersionTestSuite.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/VersionTestSuite.java new file mode 100644 index 0000000000..18cf965658 --- /dev/null +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/VersionTestSuite.java @@ -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 . + */ +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 +{ +} diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/system/DataLoadSystemTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/system/DataLoadSystemTest.java index 3cb06071bd..7c957d5ad8 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/system/DataLoadSystemTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/system/DataLoadSystemTest.java @@ -7,7 +7,6 @@ import java.util.List; import java.util.Map; 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.record.RecordService; import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService; diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java index 1683e05449..5f8906475b 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java @@ -72,6 +72,7 @@ import org.alfresco.service.cmr.site.SiteInfo; import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.cmr.site.SiteVisibility; 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.QName; 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 ASPECT_CUSTOM_ASPECT = QName.createQName(URI, "customAspect"); protected QName ASPECT_RECORD_META_DATA = QName.createQName(URI, "recordMetaData"); + + /** test data */ + protected String NAME_DM_DOCUMENT = "collabDocument.txt"; /** admin user */ protected static final String ADMIN_USER = "admin"; @@ -130,6 +134,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase protected TaggingService taggingService; protected ActionService actionService; protected OwnableService ownableService; + protected VersionService versionService; /** RM Services */ protected DispositionService dispositionService; @@ -364,6 +369,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase taggingService = (TaggingService)applicationContext.getBean("TaggingService"); actionService = (ActionService)applicationContext.getBean("ActionService"); ownableService = (OwnableService)applicationContext.getBean("OwnableService"); + versionService = (VersionService)applicationContext.getBean("VersionService"); // Get RM services dispositionService = (DispositionService)applicationContext.getBean("DispositionService"); @@ -736,7 +742,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase // create a folder and documents 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(); dmConsumerNodeRef = createPerson(dmConsumer); diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/action/impl/FileReportActionUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/action/impl/FileReportActionUnitTest.java index 5da2c6697f..b24e20089a 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/action/impl/FileReportActionUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/action/impl/FileReportActionUnitTest.java @@ -51,7 +51,7 @@ public class FileReportActionUnitTest extends BaseUnitTest * @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest#before() */ @Override - public void before() + public void before() throws Exception { super.before(); diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/condition/HoldCapabilityConditionUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/condition/HoldCapabilityConditionUnitTest.java index 14cee5c43a..0f0eb1bf68 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/condition/HoldCapabilityConditionUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/condition/HoldCapabilityConditionUnitTest.java @@ -67,7 +67,7 @@ public class HoldCapabilityConditionUnitTest extends BaseUnitTest */ @Before @Override - public void before() + public void before() throws Exception { super.before(); diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/hold/HoldServiceImplUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/hold/HoldServiceImplUnitTest.java index a275d7260b..4b017a54cf 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/hold/HoldServiceImplUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/hold/HoldServiceImplUnitTest.java @@ -77,7 +77,7 @@ public class HoldServiceImplUnitTest extends BaseUnitTest @Before @Override - public void before() + public void before() throws Exception { super.before(); diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/job/DispositionLifecycleJobExecuterUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/job/DispositionLifecycleJobExecuterUnitTest.java index 8d82002c19..8c1962dbaa 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/job/DispositionLifecycleJobExecuterUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/job/DispositionLifecycleJobExecuterUnitTest.java @@ -72,7 +72,7 @@ public class DispositionLifecycleJobExecuterUnitTest extends BaseUnitTest */ @Override @Before - public void before() + public void before() throws Exception { super.before(); diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/FrozenEvaluatorUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/FrozenEvaluatorUnitTest.java index 22d3cf8b37..e8d510a30a 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/FrozenEvaluatorUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/FrozenEvaluatorUnitTest.java @@ -50,7 +50,7 @@ public class FrozenEvaluatorUnitTest extends BaseUnitTest @Before @Override - public void before() + public void before() throws Exception { super.before(); diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/TransferEvaluatorUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/TransferEvaluatorUnitTest.java index 0d8d460860..2dfdd1b359 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/TransferEvaluatorUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/TransferEvaluatorUnitTest.java @@ -51,7 +51,7 @@ public class TransferEvaluatorUnitTest extends BaseUnitTest @Spy @InjectMocks TransferEvaluator transferEvaluator; @Override - public void before() + public void before() throws Exception { super.before(); diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImplUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImplUnitTest.java index 241e705d61..a7c0d38e8a 100755 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImplUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImplUnitTest.java @@ -55,7 +55,7 @@ public class RecordServiceImplUnitTest extends BaseUnitTest @SuppressWarnings("unchecked") @Before @Override - public void before() + public void before() throws Exception { super.before(); diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/BaseHoldWebScriptUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/BaseHoldWebScriptUnitTest.java index 178dc61fa4..16196af815 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/BaseHoldWebScriptUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/BaseHoldWebScriptUnitTest.java @@ -27,7 +27,7 @@ public abstract class BaseHoldWebScriptUnitTest extends BaseWebScriptUnitTest * @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest#before() */ @Override - public void before() + public void before() throws Exception { super.before(); diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionServiceImplUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionServiceImplUnitTest.java index f3eac28f0b..3935ebb7c3 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionServiceImplUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionServiceImplUnitTest.java @@ -83,7 +83,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest * @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest#before() */ @Override - public void before() + public void before() throws Exception { super.before(); diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/AllUnitTestSuite.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/AllUnitTestSuite.java index c034f95cdb..3e76c491e2 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/AllUnitTestSuite.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/AllUnitTestSuite.java @@ -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.HoldPutUnitTest; 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.version.RecordableVersionServiceImplUnitTest; import org.alfresco.repo.action.parameter.DateParameterProcessorUnitTest; import org.junit.runner.RunWith; import org.junit.runners.Suite; @@ -57,7 +59,8 @@ import org.junit.runners.Suite.SuiteClasses; // services RecordServiceImplUnitTest.class, HoldServiceImplUnitTest.class, - //FilePlanPermissionServiceImplUnitTest.class, + FilePlanPermissionServiceImplUnitTest.class, + RecordableVersionServiceImplUnitTest.class, // evaluators TransferEvaluatorUnitTest.class, diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseUnitTest.java index 1686c07440..fe20b2ebc6 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseUnitTest.java @@ -23,6 +23,7 @@ import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; 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.role.FilePlanRoleService; 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.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; 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.CopyService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; @@ -77,7 +82,7 @@ import org.springframework.context.ApplicationContext; * @author Roy Wetherall * @since 2.2 */ -public class BaseUnitTest implements RecordsManagementModel +public class BaseUnitTest implements RecordsManagementModel, ContentModel { protected NodeRef filePlanComponent; protected NodeRef filePlan; @@ -95,6 +100,9 @@ public class BaseUnitTest implements RecordsManagementModel @Mock(name="searchService") protected SearchService mockedSearchService; @Mock(name="retryingTransactionHelper") protected RetryingTransactionHelper mockedRetryingTransactionHelper; @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 */ @Mock(name="filePlanService") protected FilePlanService mockedFilePlanService; @@ -105,6 +113,7 @@ public class BaseUnitTest implements RecordsManagementModel @Mock(name="reportService") protected ReportService mockedReportService; @Mock(name="filePlanRoleService") protected FilePlanRoleService mockedFilePlanRoleService; @Mock(name="recordsManagementAuditService") protected RecordsManagementAuditService mockedRecordsManagementAuditService; + @Mock(name="policyBehaviourFilter") protected BehaviourFilter mockedBehaviourFilter; /** application context mock */ @Mock(name="applicationContext") protected ApplicationContext mockedApplicationContext; @@ -118,7 +127,7 @@ public class BaseUnitTest implements RecordsManagementModel */ @SuppressWarnings("unchecked") @Before - public void before() + public void before() throws Exception { 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).getParentAssocs(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); } + /** + * 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. * @@ -268,6 +290,30 @@ public class BaseUnitTest implements RecordsManagementModel } 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. diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/util/BeanExtenderUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/util/BeanExtenderUnitTest.java index 5f2a932261..6aa7fba604 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/util/BeanExtenderUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/util/BeanExtenderUnitTest.java @@ -61,7 +61,7 @@ public class BeanExtenderUnitTest extends BaseUnitTest @InjectMocks private BeanExtender beanExtender; @Override - public void before() + public void before() throws Exception { super.before(); diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionServiceImplUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionServiceImplUnitTest.java new file mode 100644 index 0000000000..7e5b76ac1f --- /dev/null +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionServiceImplUnitTest.java @@ -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 . + */ +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 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(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); + } +} \ No newline at end of file diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/version/TestRecordableVersionServiceImpl.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/version/TestRecordableVersionServiceImpl.java new file mode 100644 index 0000000000..69cad5317d --- /dev/null +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/version/TestRecordableVersionServiceImpl.java @@ -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 . + */ +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 versionProperties,PolicyScope nodeDetails) + { + } + + @Override + protected String invokeCalculateVersionLabel(QName classRef, Version preceedingVersion, int versionNumber, Map versionProperties) + { + return "1.1"; + } +} \ No newline at end of file