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()