RM-585: A user can create a rule to create a record.

* "hide record" parameter added
 * file plan service extended further
 * some simple utilities added to soak up common service code



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@45956 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2013-01-29 07:27:53 +00:00
parent 8ba3c72915
commit 8b70b49f79
12 changed files with 280 additions and 80 deletions

View File

@@ -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<NodeRef> getFilePlans();
// /**
// * Specify the store which should be searched.
// *
// * @see RecordsManagementService#getFilePlans()
// *
// * @param storeRef store reference
// * @return List<NodeRef> list of record management root nodes
// */
// @Deprecated
// List<NodeRef> getRecordsManagementRoots(StoreRef storeRef);
// TODO NodeRef getFilePlanById(String id);
/**

View File

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

View File

@@ -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<ParameterDefinition> 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)));
}
}

View File

@@ -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);
}

View File

@@ -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.");
}

View File

@@ -57,9 +57,20 @@ public interface RecordService
/**
* Creates a new unfiled record from an existing node.
* <p>
* 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);

View File

@@ -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<QName, Serializable> aspectProperties = new HashMap<QName, Serializable>(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;
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}