diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-record-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-record-context.xml index 139168556d..a4cac911f0 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-record-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-record-context.xml @@ -238,4 +238,20 @@ + + + + + + + + + + + + + + + \ No newline at end of file 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 fb32d35ece..bbed6263de 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 @@ -28,13 +28,15 @@ rm.action.no-open-record-folder=Unable to open record folder, because node is no rm.action.not-hold-type=Can not relinquish hold, because node is not of type {0}. (actionedUponNodeRef={1}) rm.action.no-read-mime-message=Unable to read mime message, because {0}. rm.action.email-declared=Can not split email, because record has already been declared. (actionedUponNodeRef={0}) -rm.action.email-not-record=Can no split email, because node is not a record. (actionedUponNodeRef={0}) +rm.action.email-not-record=Can no split email, because node is not a record. (actionedUponNodeRef={0}) rm.action.email-create-child-assoc=Unable to create custom child association. rm.action.node-already-transfer=Node is already being transfered. rm.action.node-not-transfer=Node is not a transfer object. rm.action.undo-not-last=Can not undo cut off, because last disposition action was not cut off. rm.action.records_only_undeclared=Only records can be undeclared. rm.action.event-not-undone=The event {0} can not be undone, because it is not defined on the disposition lifecycle. +rm.action.reject-no-reason=Can not reject a record without a reason. +rm.action.reject-only-unfiled-records=Can only reject unfiled records. # # i18n for Rule Actions # diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml index 35335fb8e4..d9d5359bec 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml @@ -1149,6 +1149,16 @@ + + + The reject reason of a record + + + d:text + + + + \ No newline at end of file diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml index 68e3593260..52d279b14c 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml @@ -11,9 +11,9 @@ - + - + @@ -33,10 +33,10 @@ - - @@ -47,7 +47,7 @@ - + @@ -59,14 +59,14 @@ - + - + - - + + @@ -87,11 +87,11 @@ - - - - - + + + + + @@ -112,11 +112,11 @@ - - - + + + - + @@ -147,11 +147,11 @@ ${rm.ghosting.enabled} - - + + - + @@ -172,11 +172,11 @@ - + - + - + @@ -197,11 +197,11 @@ - - - + + + - + @@ -222,11 +222,11 @@ - - - + + + - + @@ -247,11 +247,11 @@ - - - + + + - + @@ -272,12 +272,12 @@ - + - - + + - + @@ -298,9 +298,9 @@ - + - + @@ -324,7 +324,7 @@ - + @@ -349,9 +349,9 @@ - + - + @@ -364,9 +364,9 @@ - + - + @@ -389,9 +389,9 @@ - - - + + + @@ -414,9 +414,9 @@ - - - + + + @@ -439,12 +439,12 @@ - - - + + + - + @@ -465,13 +465,13 @@ - + - + - + @@ -492,16 +492,16 @@ - - - - + + - + @@ -522,12 +522,12 @@ - + - - + + - + @@ -548,10 +548,10 @@ - + - - + + @@ -574,13 +574,13 @@ - + - - + + - + @@ -591,12 +591,12 @@ - + - - + + - + @@ -617,13 +617,13 @@ - + - - + + - + @@ -634,22 +634,22 @@ - + - - + + - - + + - - - + + + @@ -670,10 +670,33 @@ - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction.execute=RM_ALLOW + org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction.*=RM_ALLOW + org.alfresco.repo.action.executer.ActionExecuter.*=RM_ALLOW + + + + + + \ No newline at end of file diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml index 81b7871b17..41141a66d0 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml @@ -675,4 +675,15 @@ + + + + + RECORD + + + + + diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/RejectAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/RejectAction.java new file mode 100644 index 0000000000..06e3f5c7b4 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/RejectAction.java @@ -0,0 +1,92 @@ +/* + * 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.action.impl; + +import java.io.Serializable; +import java.util.Map; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.repository.NodeRef; +import org.apache.commons.lang.StringUtils; +import org.springframework.extensions.surf.util.I18NUtil; + +/** + * Reject action for an unfiled record + * + * @author Tuna Aksoy + * @since 2.1 + */ +public class RejectAction extends RMActionExecuterAbstractBase +{ + /** Message properties */ + private static final String MSG_REJECT_NO_REASON = "rm.action.reject-no-reason"; + private static final String MSG_REJECT_ONLY_UNFILED_RECORDS = "rm.action.reject-only-unfiled-records"; + + /** Parameter names */ + public static final String PARAM_REASON = "reason"; + + /** + * @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef) + */ + @Override + protected void executeImpl(Action action, NodeRef actionedUponNodeRef) + { + recordService.rejectRecord(actionedUponNodeRef, (String) action.getParameterValue(PARAM_REASON)); + } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase#isExecutableImpl(org.alfresco.service.cmr.repository.NodeRef, java.util.Map, boolean) + */ + @Override + protected boolean isExecutableImpl(NodeRef filePlanComponent, + Map parameters, boolean throwException) + { + if (recordService.isRecord(filePlanComponent) == true && recordService.isFiled(filePlanComponent) == false) + { + if (parameters != null && StringUtils.isNotBlank((String) parameters.get(PARAM_REASON))) + { + return true; + } + else + { + if (throwException) + { + throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_REJECT_NO_REASON)); + } + else + { + return false; + } + } + } + else + { + if (throwException) + { + throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_REJECT_ONLY_UNFILED_RECORDS)); + } + else + { + return false; + } + } + } +} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java index 9e85feb13f..eeacecc3d2 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java @@ -234,4 +234,8 @@ public interface RecordsManagementModel extends RecordsManagementCustomModel // Original location of a record public static final QName ASPECT_ORIGINAL_LOCATION = QName.createQName(RM_URI, "originalLocation"); public static final QName PROP_ORIGINAL_LOCATION = QName.createQName(RM_URI, "orgLocation"); + + // Reject reason of a record + public static final QName ASPECT_REJECT_REASON_RECORD = QName.createQName(RM_URI, "rejectReasonRecord"); + public static final QName PROP_REJECT_REASON = QName.createQName(RM_URI, "rejectReason"); } 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 51002e5e5d..6430848801 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 @@ -26,7 +26,7 @@ import org.alfresco.service.namespace.QName; /** * Record Service Interface. - * + * * @author Roy Wetherall * @since 2.1 */ @@ -34,14 +34,14 @@ public interface RecordService { /** * Gets a list of all the record meta-data aspects - * + * * @return {@link Set}<{@link QName}> list of record meta-data aspects */ Set getRecordMetaDataAspects(); /** * Checks whether if the given node reference is a record or not - * + * * @param nodeRef node reference to be checked * @return boolean true if the node reference is a record, false otherwise */ @@ -49,36 +49,44 @@ public interface RecordService /** * Indicates whether the record is declared - * + * * @param nodeRef node reference of the record for which the check would be performed * @return boolean true if record is declared, false otherwise */ - boolean isDeclared(NodeRef nodeRef); + boolean isDeclared(NodeRef nodeRef); /** * 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); - + /** * Indicates whether the record is filed or not - * + * * @param nodeRef record * @return boolean true if filed, false otherwise */ boolean isFiled(NodeRef record); + + /** + * Rejects a node with the provided reason + * + * @param nodeRef node reference + * @param reason reject reason + */ + void rejectRecord(NodeRef nodeRef, String reason); } 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 8a7ed841a0..c8274b612e 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 @@ -23,6 +23,7 @@ import java.util.Calendar; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -90,7 +91,7 @@ public class RecordServiceImpl implements RecordService, /** Disposition service */ private DispositionService dispositionService; - + /** File plan service */ private FilePlanService filePlanService; @@ -167,7 +168,7 @@ public class RecordServiceImpl implements RecordService, { this.dispositionService = dispositionService; } - + /** * @param filePlanService file plan service */ @@ -268,7 +269,7 @@ public class RecordServiceImpl implements RecordService, { 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) */ @@ -277,7 +278,7 @@ public class RecordServiceImpl implements RecordService, ParameterCheck.mandatory("filePlan", filePlan); 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 @@ -322,10 +323,10 @@ public class RecordServiceImpl implements RecordService, makeRecord(nodeRef); if (isLinked == true) - { + { // maintain the original primary location nodeService.addChild(parentAssoc.getParentRef(), nodeRef, parentAssoc.getTypeQName(), parentAssoc.getQName()); - + // set the readers extendedSecurityService.setExtendedReaders(nodeRef, readers); } @@ -425,4 +426,54 @@ public class RecordServiceImpl implements RecordService, } } } + + @Override + public void rejectRecord(final NodeRef nodeRef, String reason) + { + ParameterCheck.mandatory("NodeRef", nodeRef); + ParameterCheck.mandatoryString("Reason", reason); + + // do the work of rejecting the record as the system user + AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public Void doWork() throws Exception + { + // first remove the secondary link association + NodeRef originalLocation = (NodeRef) nodeService.getProperty(nodeRef, PROP_ORIGINAL_LOCATION); + List parentAssocs = nodeService.getParentAssocs(nodeRef); + for (ChildAssociationRef childAssociationRef : parentAssocs) + { + if (childAssociationRef.isPrimary() == false && childAssociationRef.getParentRef().equals(originalLocation)) + { + nodeService.removeChildAssociation(childAssociationRef); + break; + } + } + + // remove the "record" and "file plan component" aspects + nodeService.removeAspect(nodeRef, RecordsManagementModel.ASPECT_RECORD); + nodeService.removeAspect(nodeRef, ASPECT_FILE_PLAN_COMPONENT); + + // remove "identifier" property + nodeService.removeProperty(nodeRef, PROP_IDENTIFIER); + + // get the records primary parent association + ChildAssociationRef parentAssoc = nodeService.getPrimaryParent(nodeRef); + + // save the reject reason + Map aspectProperties = new HashMap(1); + aspectProperties.put(PROP_REJECT_REASON, (Serializable) parentAssoc.getParentRef()); + nodeService.addAspect(nodeRef, ASPECT_REJECT_REASON_RECORD, aspectProperties); + + // move the record into the collaboration site + nodeService.moveNode(nodeRef, originalLocation, ContentModel.ASSOC_CONTAINS, parentAssoc.getQName()); + + // remove all extended readers + extendedSecurityService.removeAllExtendedReaders(nodeRef); + + return null; + } + }); + } }