diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/actions.properties b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/actions.properties index bd63793b0a..fb32d35ece 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/actions.properties +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/actions.properties @@ -41,3 +41,5 @@ rm.action.event-not-undone=The event {0} can not be undone, because it is not de # Create record create-record.title=Create record create-record.description=Creates a Record from an existing document. +create-record.file-plan.display-label=File plan +create-record.hide-record.display-label=Hide Record diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml index 047c7b0778..aea15cc0e3 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml @@ -27,6 +27,11 @@ + + + + + @@ -432,10 +437,9 @@ - - diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementService.java index 3703074787..1f8d5a4ff2 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementService.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementService.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService; import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.service.cmr.repository.NodeRef; @@ -87,7 +88,10 @@ public interface RecordsManagementService * * @param nodeRef node reference * @return boolean true if node is a file plan node + * + * @deprecated as of 2.1, see {@link FilePlanService#isFilePlan(NodeRef)} */ + @Deprecated boolean isFilePlan(NodeRef nodeRef); /** @@ -122,7 +126,7 @@ public interface RecordsManagementService * @param nodeRef node reference * @return boolean true if a metadata stub, false otherwise * - * @since + * @since 2.0 */ boolean isMetadataStub(NodeRef nodeRef); @@ -164,17 +168,6 @@ public interface RecordsManagementService */ List getFilePlans(); -// /** -// * Specify the store which should be searched. -// * -// * @see RecordsManagementService#getFilePlans() -// * -// * @param storeRef store reference -// * @return List list of record management root nodes -// */ -// @Deprecated -// List getRecordsManagementRoots(StoreRef storeRef); - // TODO NodeRef getFilePlanById(String id); /** diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceImpl.java index ba4206e6f1..341b4dc8ab 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceImpl.java @@ -33,16 +33,15 @@ import org.alfresco.model.RenditionModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementCustomModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService; +import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl; import org.alfresco.repo.domain.node.NodeDAO; import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.policy.Behaviour.NotificationFrequency; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; -import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; @@ -56,7 +55,8 @@ import org.springframework.extensions.surf.util.I18NUtil; * * @author Roy Wetherall */ -public class RecordsManagementServiceImpl implements RecordsManagementService, +public class RecordsManagementServiceImpl extends ServiceBaseImpl + implements RecordsManagementService, RecordsManagementModel, RecordsManagementPolicies.OnCreateReference, RecordsManagementPolicies.OnRemoveReference @@ -86,12 +86,6 @@ public class RecordsManagementServiceImpl implements RecordsManagementService, /** Service registry */ private RecordsManagementServiceRegistry serviceRegistry; - /** Dictionary service */ - private DictionaryService dictionaryService; - - /** Node service */ - private NodeService nodeService; - /** Node DAO */ private NodeDAO nodeDAO; @@ -126,16 +120,6 @@ public class RecordsManagementServiceImpl implements RecordsManagementService, this.policyComponent = policyComponent; } - /** - * Set search service - * - * @param nodeService search service - */ - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - /** * Set the node DAO object * @@ -421,24 +405,7 @@ public class RecordsManagementServiceImpl implements RecordsManagementService, public boolean isRecordsManagementContainer(NodeRef nodeRef) { return instanceOf(nodeRef, TYPE_RECORDS_MANAGEMENT_CONTAINER); - } - - /** - * Utility method to safely and quickly determine if a node is a type (or sub-type) of the one specified. - */ - private boolean instanceOf(NodeRef nodeRef, QName ofClassName) - { - ParameterCheck.mandatory("nodeRef", nodeRef); - ParameterCheck.mandatory("ofClassName", ofClassName); - boolean result = false; - if (nodeService.exists(nodeRef) == true && - (ofClassName.equals(nodeService.getType(nodeRef)) == true || - dictionaryService.isSubClass(nodeService.getType(nodeRef), ofClassName) == true)) - { - result = true; - } - return result; - } + } /** * @see org.alfresco.module.org_alfresco_module_rm.RecordsManagementService#isFilePlanComponent(org.alfresco.service.cmr.repository.NodeRef) diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/CreateRecordAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/CreateRecordAction.java index e405fa0034..683e0a51c4 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/CreateRecordAction.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/CreateRecordAction.java @@ -53,6 +53,7 @@ public class CreateRecordAction extends ActionExecuterAbstractBase /** Parameter names */ public static final String PARAM_FILE_PLAN = "file-plan"; + public static final String PARAM_HIDE_RECORD = "hide-record"; /** Records management service */ private RecordsManagementService recordsManagementService; @@ -141,9 +142,12 @@ public class CreateRecordAction extends ActionExecuterAbstractBase throw new AlfrescoRuntimeException("Can not create record, because the provided file plan node reference is not a file plan."); } } - + + // indicate whether the record should be hidden or not + boolean hideRecord = ((Boolean)action.getParameterValue(PARAM_HIDE_RECORD)).booleanValue(); + // create record from existing document - recordService.createRecord(filePlan, actionedUponNodeRef); + recordService.createRecord(filePlan, actionedUponNodeRef, !hideRecord); } } @@ -153,8 +157,9 @@ public class CreateRecordAction extends ActionExecuterAbstractBase @Override protected void addParameterDefinitions(List params) { - // Optional parameter used to specify the file plan - params.add(new ParameterDefinitionImpl(PARAM_FILE_PLAN, DataTypeDefinition.NODE_REF, false, getParamDisplayLabel(PARAM_FILE_PLAN))); + // NOTE: commented out for now so that it doesn't appear in the UI ... enable later when multi-file plan support is added + //params.add(new ParameterDefinitionImpl(PARAM_FILE_PLAN, DataTypeDefinition.NODE_REF, false, getParamDisplayLabel(PARAM_FILE_PLAN))); + params.add(new ParameterDefinitionImpl(PARAM_HIDE_RECORD, DataTypeDefinition.BOOLEAN, true, getParamDisplayLabel(PARAM_HIDE_RECORD))); } } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanService.java index 14ba581eda..9676e36bba 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanService.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanService.java @@ -20,6 +20,8 @@ package org.alfresco.module.org_alfresco_module_rm.fileplan; import org.alfresco.service.cmr.repository.NodeRef; +import com.hazelcast.impl.Node; + /** * File plan service interface. * @@ -28,10 +30,37 @@ import org.alfresco.service.cmr.repository.NodeRef; */ public interface FilePlanService { + /** + * Indicates whether the given node is file plan node or not. + * + * @param nodeRef node reference + * @return boolean true if node is a file plan node + */ + boolean isFilePlan(NodeRef nodeRef); + + /** + * Indicates whether the unfiled container exists for a given file plan or not. + * + * @param filePlan file plan + * @return boolean true if unfiled container exists, false otherwise + */ boolean existsUnfiledContainer(NodeRef filePlan); + /** + * Gets the unfiled container for a given file plan. Returns null if + * none. + * + * @param filePlan file plan + * @return {@link NodeRef} unfiled container, null if none + */ NodeRef getUnfiledContainer(NodeRef filePlan); + /** + * Creates, and returns, a unfiled container for a given file plan. + * + * @param filePlan file plan + * @return {@link Node} unfiled container + */ NodeRef createUnfiledContainer(NodeRef filePlan); } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanServiceImpl.java index 4b04152756..4574c3068e 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanServiceImpl.java @@ -25,14 +25,13 @@ import java.util.Map; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; -import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService; import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority; +import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.QName; import org.alfresco.util.ParameterCheck; @@ -46,7 +45,8 @@ import org.springframework.context.ApplicationContextAware; * @author Roy Wetherall * @since 2.1 */ -public class FilePlanServiceImpl implements FilePlanService, +public class FilePlanServiceImpl extends ServiceBaseImpl + implements FilePlanService, RecordsManagementModel, ApplicationContextAware { @@ -55,9 +55,7 @@ public class FilePlanServiceImpl implements FilePlanService, private static final QName QNAME_UNFILED_CONTAINER = QName.createQName(RM_URI, NAME_UNFILED_CONTAINER); /** Services */ - private NodeService nodeService; private PermissionService permissionService; - private RecordsManagementService recordsManagementService; /** Application context */ private ApplicationContext applicationContext; @@ -68,11 +66,6 @@ public class FilePlanServiceImpl implements FilePlanService, this.applicationContext = applicationContext; } - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - /** * NOTE: for some reason spring couldn't cope with the circular references between these two * beans so we need to grab this one manually. @@ -84,16 +77,25 @@ public class FilePlanServiceImpl implements FilePlanService, return (FilePlanRoleService)applicationContext.getBean("FilePlanRoleService"); } + /** + * @param permissionService permission service + */ public void setPermissionService(PermissionService permissionService) { this.permissionService = permissionService; } - public void setRecordsManagementService(RecordsManagementService recordsManagementService) + /** + * @see org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService#isFilePlan(org.alfresco.service.cmr.repository.NodeRef) + */ + public boolean isFilePlan(NodeRef nodeRef) { - this.recordsManagementService = recordsManagementService; + return instanceOf(nodeRef, TYPE_FILE_PLAN); } + /** + * @see org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService#existsUnfiledContainer(org.alfresco.service.cmr.repository.NodeRef) + */ @Override public boolean existsUnfiledContainer(NodeRef filePlan) { @@ -107,7 +109,7 @@ public class FilePlanServiceImpl implements FilePlanService, public NodeRef getUnfiledContainer(NodeRef filePlan) { ParameterCheck.mandatory("filePlan", filePlan); - if (recordsManagementService.isFilePlan(filePlan) == false) + if (isFilePlan(filePlan) == false) { throw new AlfrescoRuntimeException("Unable to get the unfiled container, because passed node is not a file plan."); } @@ -134,7 +136,7 @@ public class FilePlanServiceImpl implements FilePlanService, public NodeRef createUnfiledContainer(NodeRef filePlan) { ParameterCheck.mandatory("filePlan", filePlan); - if (recordsManagementService.isFilePlan(filePlan) == false) + if (isFilePlan(filePlan) == false) { throw new AlfrescoRuntimeException("Unable to create unfiled container, because passed node is not a file plan."); } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java index 13d3ee41ec..51002e5e5d 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java @@ -57,9 +57,20 @@ public interface RecordService /** * Creates a new unfiled record from an existing node. + *

+ * Note that the node reference of the record will be the same as the origional + * document. * * @param filePlan The filePlan in which the record should be placed * @param nodeRef The node from which the record will be created + * @param isLinked indicates if the newly created record is linked to it's original location or not. + */ + void createRecord(NodeRef filePlan, NodeRef nodeRef, boolean isLinked); + + /** + * Links the newly created record to it's original location. + * + * @see #createRecord(NodeRef, NodeRef, boolean) */ void createRecord(NodeRef filePlan, NodeRef nodeRef); diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java index a0e75b5b9a..8a7ed841a0 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java @@ -261,15 +261,23 @@ public class RecordServiceImpl implements RecordService, } /** - * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#createRecord(org.alfresco.service.cmr.repository.NodeRef, - * org.alfresco.service.cmr.repository.NodeRef) + * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#createRecord(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef) */ @Override - public void createRecord(final NodeRef filePlan, final NodeRef nodeRef) + public void createRecord(NodeRef filePlan, NodeRef nodeRef) + { + createRecord(filePlan, nodeRef, true); + } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#createRecord(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef, boolean) + */ + public void createRecord(final NodeRef filePlan, final NodeRef nodeRef, final boolean isLinked) { ParameterCheck.mandatory("filePlan", filePlan); - ParameterCheck.mandatory("document", nodeRef); - + ParameterCheck.mandatory("nodeRef", nodeRef); + ParameterCheck.mandatory("isLinked", isLinked); + if (nodeService.hasAspect(nodeRef, ASPECT_RECORD) == false) { // first we do a sanity check to ensure that the user has at least write permissions on the document @@ -305,19 +313,22 @@ public class RecordServiceImpl implements RecordService, // move the document into the file plan nodeService.moveNode(nodeRef, newRecordContainer, ContentModel.ASSOC_CONTAINS, parentAssoc.getQName()); - // maintain the original primary location - ChildAssociationRef child = nodeService.addChild(parentAssoc.getParentRef(), nodeRef, parentAssoc.getTypeQName(), parentAssoc.getQName()); - // Add the information about the original location Map aspectProperties = new HashMap(1); - aspectProperties.put(PROP_ORIGINAL_LOCATION, (Serializable) child.getParentRef()); + aspectProperties.put(PROP_ORIGINAL_LOCATION, (Serializable) parentAssoc.getParentRef()); nodeService.addAspect(nodeRef, ASPECT_ORIGINAL_LOCATION, aspectProperties); // make the document a record makeRecord(nodeRef); - // set the readers - extendedSecurityService.setExtendedReaders(nodeRef, readers); + if (isLinked == true) + { + // maintain the original primary location + nodeService.addChild(parentAssoc.getParentRef(), nodeRef, parentAssoc.getTypeQName(), parentAssoc.getQName()); + + // set the readers + extendedSecurityService.setExtendedReaders(nodeRef, readers); + } return null; } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java new file mode 100644 index 0000000000..46fabeec30 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2005-2012 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.util; + +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.ParameterCheck; + +/** + * Helper base class for service implementations. + * + * @author Roy Wetherall + * @since 2.1 + */ +public class ServiceBaseImpl +{ + /** Node service */ + protected NodeService nodeService; + + /** Dictionary service */ + protected DictionaryService dictionaryService; + + /** + * @param nodeService node service + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + /** + * @param dictionaryService dictionary service + */ + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + /** + * Utility method to safely and quickly determine if a node is a type (or sub-type) of the one specified. + * + * @param nodeRef node reference + * @param ofClassName class name to check + */ + protected boolean instanceOf(NodeRef nodeRef, QName ofClassName) + { + ParameterCheck.mandatory("nodeRef", nodeRef); + ParameterCheck.mandatory("ofClassName", ofClassName); + boolean result = false; + if (nodeService.exists(nodeRef) == true && + (ofClassName.equals(nodeService.getType(nodeRef)) == true || + dictionaryService.isSubClass(nodeService.getType(nodeRef), ofClassName) == true)) + { + result = true; + } + return result; + } + +} diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/action/CreateRecordActionTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/action/CreateRecordActionTest.java index b1fa2a2681..118f93497c 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/action/CreateRecordActionTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/action/CreateRecordActionTest.java @@ -68,6 +68,7 @@ public class CreateRecordActionTest extends BaseRMTestCase assertEquals(AccessStatus.DENIED, dmPermissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS)); Action action = dmActionService.createAction(CreateRecordAction.NAME); + action.setParameterValue(CreateRecordAction.PARAM_HIDE_RECORD, false); dmActionService.executeAction(action, dmDocument); return null; diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordServiceImplTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordServiceImplTest.java index 498b1875d5..046e27d927 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordServiceImplTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordServiceImplTest.java @@ -211,6 +211,8 @@ public class RecordServiceImplTest extends BaseRMTestCase @Override public Void run() { + NodeRef originalLocation = nodeService.getPrimaryParent(dmDocument).getParentRef(); + assertFalse(recordService.isRecord(dmDocument)); assertFalse(extendedSecurityService.hasExtendedReaders(dmDocument)); @@ -253,12 +255,108 @@ public class RecordServiceImplTest extends BaseRMTestCase assertTrue(recordService.isRecord(dmDocument)); assertTrue(extendedSecurityService.hasExtendedReaders(dmDocument)); assertFalse(recordService.isFiled(dmDocument)); + + // show that the record has meta-data about it's original location + assertTrue(nodeService.hasAspect(dmDocument, ASPECT_ORIGINAL_LOCATION)); + assertEquals(originalLocation, nodeService.getProperty(dmDocument, PROP_ORIGINAL_LOCATION)); + assertFalse(originalLocation == nodeService.getPrimaryParent(dmDocument).getParentRef()); + + // show that the record is linked to it's original location + assertEquals(2, nodeService.getParentAssocs(dmDocument).size()); return null; } }, dmCollaborator); } + public void testCreateRecordNoLink() throws Exception + { + // show that users without WRITE can not create a record from a document + doTestInTransaction(new FailureTest + ( + "Can not create a record from a document if you do not have WRITE permissions.", + AccessDeniedException.class + ) + { + public void run() throws Exception + { + recordService.createRecord(filePlan, dmDocument, false); + } + }, dmConsumer); + + // create record from document + final NodeRef originalLocation = doTestInTransaction(new Test() + { + @Override + public NodeRef run() + { + NodeRef originalLocation = nodeService.getPrimaryParent(dmDocument).getParentRef(); + + assertFalse(recordService.isRecord(dmDocument)); + assertFalse(extendedSecurityService.hasExtendedReaders(dmDocument)); + + checkPermissions(READ_RECORDS, + AccessStatus.DENIED, // file plan + AccessStatus.DENIED, // unfiled container + AccessStatus.DENIED, // record category + AccessStatus.DENIED, // record folder + AccessStatus.DENIED); // doc/record + + assertEquals(AccessStatus.DENIED, + dmPermissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS)); + + checkPermissions(FILING, + AccessStatus.DENIED, // file plan + AccessStatus.DENIED, // unfiled container + AccessStatus.DENIED, // record category + AccessStatus.DENIED, // record folder + AccessStatus.DENIED); // doc/record + + recordService.createRecord(filePlan, dmDocument, false); + + checkPermissions(READ_RECORDS, + AccessStatus.DENIED, // file plan + AccessStatus.DENIED, // unfiled container + AccessStatus.DENIED, // record category + AccessStatus.DENIED, // record folder + AccessStatus.DENIED); // doc/record + + assertEquals(AccessStatus.DENIED, + dmPermissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS)); + + checkPermissions(FILING, + AccessStatus.DENIED, // file plan + AccessStatus.DENIED, // unfiled container + AccessStatus.DENIED, // record category + AccessStatus.DENIED, // record folder + AccessStatus.DENIED); // doc/record + + return originalLocation; + } + }, dmCollaborator); + + doTestInTransaction(new Test() + { + @Override + public Void run() + { + assertTrue(recordService.isRecord(dmDocument)); + assertFalse(extendedSecurityService.hasExtendedReaders(dmDocument)); + assertFalse(recordService.isFiled(dmDocument)); + + // show that the record has meta-data about it's original location + assertTrue(nodeService.hasAspect(dmDocument, ASPECT_ORIGINAL_LOCATION)); + assertEquals(originalLocation, nodeService.getProperty(dmDocument, PROP_ORIGINAL_LOCATION)); + assertFalse(originalLocation == nodeService.getPrimaryParent(dmDocument).getParentRef()); + + // show that the record is linked to it's original location + assertEquals(1, nodeService.getParentAssocs(dmDocument).size()); + + return null; + } + }, rmAdminName); + } + public void testFileNewContent() throws Exception { doTestInTransaction(new Test()