diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/action-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/action-context.xml new file mode 100644 index 0000000000..cbdd79e0ec --- /dev/null +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/action-context.xml @@ -0,0 +1,45 @@ + + + + + + + + + + alfresco.module.org_alfresco_module_rm.messages.actions + + + + + + + + + + + + {http://www.alfresco.org/model/content/1.0}content + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-audit-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-audit-context.xml index 7b6fe1e98f..e9a2abde11 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-audit-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-audit-context.xml @@ -4,7 +4,6 @@ - diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-group-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-group-context.xml index 407699cbff..224da9c985 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-group-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-group-context.xml @@ -6,6 +6,7 @@ + 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 new file mode 100644 index 0000000000..ce4c5321a9 --- /dev/null +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/actions.properties @@ -0,0 +1,53 @@ +rm.action.not-defined=The records management action {0} has not been defined. +rm.action.no-implicit-noderef=Unable to execute the records management action, because the action {0} implementation does not provide an implicit nodeRef. +rm.action.record-not-declared=Unable to execute disposition action {0}, because the record is not declared. (actionedUponNodeRef={1}) +rm.action.expected-record-level=Unable to execute disposition action {0}, because disposition is expected at the record level and this node is not a record. (actionedUponNodeRef={1}) +rm.action.not-all-records-declared=Unable to execute disposition action {0}, because not all the records in the record are declared. (actionedUponNodeRef={1}) +rm.action.not-eligible=Unable to execute disposition action {0}, because the next disposition action on the record or record folder is not eligible. (actionedUponNodeRef={1}) +rm.action.no-disposition-instructions=Unable to find disposition instructions for node. Can not execute disposition action {0}. (nodeRef={1}) +rm.action.no-disposition-lisfecycle-set=Unable to execute disposition action {0}, because node does not have a disposition life-cycle set. (nodeRef={1}) +rm.action.next-disp-not-set=Unable to execute disposition action {0}, because the next disposition action is not set. (nodeRef={1}) +rm.action.not-next-disp=Unable to execute disposition action {0}, because this is not the next disposition action for this record or record folder. (nodeRef={1}) +rm.action.not-record-folder=Unable to execute disposition action {0}, because disposition is expected at the record folder level and this node is not a record folder. (nodeRef={1}) +rm.action.actioned-upon-not-record=Can not execute action {0}, because the actioned upon node is not a Record. (filePlanComponet={1}) +rm.action.custom-aspect-not-recognised=The custom type can not be applied, because is it not recognised. (customAspect={0}) +rm.action.close-record-folder-not-folder=Unable to close record folder, because the node is not a record folder. (nodeRef={0}) +rm.action.event-no-disp-lc=The event {0} can not be completed, because it is not defined on the disposition lifecycle. +rm.action.undeclared-only-records=Only records can be undeclared. (nodeRef={0}) +rm.action.no-declare-mand-prop=Can not declare record, because not all the records mandatory properties have been set. +rm.action.ghosted-prop-update=The content properties of a previously destroyed record can not be updated. +rm.action.valid-date-disp-asof=A valid date must be specified when setting the disposition action as of date. +rm.action.disp-asof-lifecycle-applied=It is invalid to edit the disposition as of date of a record or record folder which has a lifecycle applied. +rm.action.hold-edit-reason-none=Can not edit hold reason, because no reason has been given. +rm.action.hold-edit-type=Can not edit hold reason, because actioned upon node is not of type {0}. (nodeRef={1}) +rm.action.specify-avlid-date=Must specify a valid date when setting the review as of date. +rm.action.review-details-only=Can only edit the review details of vital records. +rm.action.freeze-no-reason=Can not freeze a record without a reason. +rm.action.freeze-only-records-folders=Can only freeze records or record folders. +rm.action.no-open-record-folder=Unable to open record folder, because node is not a record folder. (actionedUponNodeRef={0}) +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-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. +# +# i18n for Rule Actions +# +# File record +file-record.title=File record +# FIXME!!! +#file-record.description=The rule is applied to all items that... +#file-record.destination-record-folder.display-label=File record +# Create record +create-record.title=Create record +# FIXME!!! +#create-record.description=The rule is applied to all items that... +# Declare record +declare-record.title=Declare record +# FIXME!!! +#declare-record.description=The rule is applied to all items that... \ 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 1feccfa8d6..bc66c31842 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 @@ -46,10 +46,13 @@ + + + + + + @@ -137,6 +143,7 @@ + @@ -223,26 +230,28 @@ - - - - - - - - - - - - + + + + + + + + + + + + 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 2c45288f94..2be23cf20e 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 @@ -34,7 +34,10 @@ - + @@ -65,7 +68,7 @@ - + @@ -95,7 +98,7 @@ - + @@ -766,5 +769,6 @@ + \ No newline at end of file diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-actions.properties b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-actions.properties index 47a031717d..22ff6e9457 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-actions.properties +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-actions.properties @@ -86,3 +86,9 @@ editDispositionActionAsOfDate.description=Edit Disposition Action As Of Date createDispositionSchedule.title=Create Disposition Schedule createDispositionSchedule.description=Create Disposition Schedule + +file-record.title=File Record +file-record.description=File a record into the file plan. + +create-record.title=Create A Record +create-record.description=Create a record from a document. diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml index a882c2d8d1..337668a427 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml @@ -39,20 +39,20 @@ @@ -60,7 +60,7 @@ @@ -68,14 +68,14 @@ @@ -83,7 +83,7 @@ @@ -100,5 +100,12 @@ + + + + + \ No newline at end of file diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-public-services-security-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-public-services-security-context.xml index 5c3e60b334..2359f12376 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-public-services-security-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-public-services-security-context.xml @@ -48,6 +48,7 @@ + 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 a6d9d1fef9..8c7d307a1c 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 @@ -915,7 +915,7 @@ - + + @@ -14,6 +15,7 @@ abstract="true"> + diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml index a403d826ef..d82e9ef861 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml @@ -2,380 +2,485 @@ - - - - - - - - - - - - - + + + + + - - - - - - - - - - + + + + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - + + + + - - - - - - - - - + + + + - - - - + + + + - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rm-server/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary-v2/rm-filters.lib.js b/rm-server/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary-v2/rm-filters.lib.js index 25a0234d47..fa31ed974e 100644 --- a/rm-server/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary-v2/rm-filters.lib.js +++ b/rm-server/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary-v2/rm-filters.lib.js @@ -179,6 +179,13 @@ Filters.getFilterParams = function RecordsManagementFilter_getFilterParams(filte filterParams.query = "+PARENT:\"" + filterData + "\""; } break; + + case "unfiledRecords": + filterParams.variablePath = false; + filterQuery = "+PATH:\"" + parsedArgs.pathNode.qnamePath + "/rma:Unfiled_x0020_Records/*\""; + filterParams.query = filterQuery + filterQueryDefaults; + + break; default: filterParams.variablePath = false; diff --git a/rm-server/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/rm-treenode.get.js b/rm-server/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/rm-treenode.get.js index 09c27856d2..8dd5e01d78 100644 --- a/rm-server/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/rm-treenode.get.js +++ b/rm-server/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/rm-treenode.get.js @@ -120,7 +120,7 @@ function itemIsAllowed(item) var typeShort = String(item.typeShort); // Don't show Hold and Transfer top-level containers - if (typeShort == "rma:hold" || typeShort == "rma:transfer") + if (typeShort == "rma:hold" || typeShort == "rma:transfer" || typeShort == "rma:unfiledRecordContainer") { return false; } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceRegistryImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceRegistryImpl.java index 9c8e94ce8d..20714b8d54 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceRegistryImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceRegistryImpl.java @@ -71,15 +71,14 @@ public class RecordsManagementServiceRegistryImpl extends ServiceDescriptorRegis { return (RecordsManagementService)getService(RECORDS_MANAGEMENT_SERVICE); } - - /** - * @see org.alfresco.module.org_alfresco_module_rm.RecordsManagementServiceRegistry#getRecordService() - */ - @Override - public RecordService getRecordService() - { - return (RecordService)getService(RECORD_SERVICE); - } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.RecordsManagementServiceRegistry#getRecordService() + */ + public RecordService getRecordService() + { + return (RecordService)getService(RECORD_SERVICE); + } /** * @see org.alfresco.module.org_alfresco_module_rm.RecordsManagementServiceRegistry#getRecordsManagementSecurityService() diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/RMActionExecuterAbstractBase.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/RMActionExecuterAbstractBase.java index 5b274609eb..3db77a7800 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/RMActionExecuterAbstractBase.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/RMActionExecuterAbstractBase.java @@ -101,6 +101,9 @@ public abstract class RMActionExecuterAbstractBase extends ActionExecuterAbstra /** Records management service */ protected RecordsManagementService recordsManagementService; + /** Record service */ + protected RecordService recordService; + /** Disposition service */ protected DispositionService dispositionService; @@ -119,9 +122,6 @@ public abstract class RMActionExecuterAbstractBase extends ActionExecuterAbstra /** Freeze Service */ protected FreezeService freezeService; - /** Record Service */ - protected RecordService recordService; - protected LinkedList capabilities = new LinkedList();; /** Default constructor */ @@ -301,12 +301,23 @@ public abstract class RMActionExecuterAbstractBase extends ActionExecuterAbstra PropertyCheck.mandatory(this, "recordsManagementService", recordsManagementService); PropertyCheck.mandatory(this, "recordsManagementAdminService", recordsManagementAdminService); PropertyCheck.mandatory(this, "recordsManagementEventService", recordsManagementEventService); + for(AbstractCapability capability : capabilities) { capability.registerAction(this); } } + /** + * Indicates whether this records management action is public or not + * + * @return boolean true if public, false otherwise + */ + public boolean isPublicAction() + { + return publicAction; + } + /** * @see org.alfresco.repo.action.CommonResourceAbstractBase#setBeanName(java.lang.String) */ diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/RMDispositionActionExecuterAbstractBase.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/RMDispositionActionExecuterAbstractBase.java index 72bd5a7861..228d0e6f84 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/RMDispositionActionExecuterAbstractBase.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/RMDispositionActionExecuterAbstractBase.java @@ -100,7 +100,7 @@ public abstract class RMDispositionActionExecuterAbstractBase extends RMActionEx if (this.recordsManagementService.isRecord(actionedUponNodeRef) == true) { // Can only execute disposition action on record if declared - if (this.recordsManagementService.isRecordDeclared(actionedUponNodeRef) == true) + if (recordService.isDeclared(actionedUponNodeRef) == true) { // Indicate that the disposition action is underway this.nodeService.setProperty(nextDispositionActionNodeRef, PROP_DISPOSITION_ACTION_STARTED_AT, new Date()); @@ -315,7 +315,7 @@ public abstract class RMDispositionActionExecuterAbstractBase extends RMActionEx if (this.recordsManagementService.isRecord(filePlanComponent) == true) { // Can only execute disposition action on record if declared - if (this.recordsManagementService.isRecordDeclared(filePlanComponent) == true) + if (recordService.isDeclared(filePlanComponent) == true) { return true; } 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 new file mode 100644 index 0000000000..c0598c8feb --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/CreateRecordAction.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2005-2011 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.dm; + +import java.util.List; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.module.org_alfresco_module_rm.record.RecordService; +import org.alfresco.repo.action.executer.ActionExecuterAbstractBase; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.action.ParameterDefinition; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; + +/** + * Creates a new record from an existing content object. + * + * Note: This is a 'normal' dm action, rather than a records management action. + * + * @author Roy Wetherall + */ +public class CreateRecordAction extends ActionExecuterAbstractBase + implements RecordsManagementModel +{ + /** Action name */ + public static final String NAME = "create-record"; + + /** Records management service */ + private RecordsManagementService recordsManagementService; + + /** Record service */ + private RecordService recordService; + + /** Node service */ + private NodeService nodeService; + + /** + * @param recordsManagementService records management service + */ + public void setRecordsManagementService(RecordsManagementService recordsManagementService) + { + this.recordsManagementService = recordsManagementService; + } + + /** + * @param recordService record service + */ + public void setRecordService(RecordService recordService) + { + this.recordService = recordService; + } + + /** + * @param nodeService node service + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + /** + * @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, final NodeRef actionedUponNodeRef) + { + // skip everything if the actioned upon node reference is already a record + if (nodeService.hasAspect(actionedUponNodeRef, ASPECT_RECORD) == false) + { + // TODO we should use the file plan passed as a parameter + // grab the file plan + List filePlans = recordsManagementService.getFilePlans(); + if (filePlans.size() == 1) + { + // TODO parameterise the action with the file plan + final NodeRef filePlan = filePlans.get(0); + + // run record creation as system + AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public Void doWork() throws Exception + { + // create record from existing document + recordService.createRecordFromDocument(filePlan, actionedUponNodeRef); + + return null; + } + }); + } + else + { + throw new AlfrescoRuntimeException("Unable to find file plan."); + } + } + } + + /** + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) + */ + @Override + protected void addParameterDefinitions(List params) + { + // TODO eventually we will need to pass in the file plan as a parameter + // TODO .. or the RM site + } + +} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/DeclareRecordAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/DeclareRecordAction.java new file mode 100644 index 0000000000..5af2af8854 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/DeclareRecordAction.java @@ -0,0 +1,219 @@ +package org.alfresco.module.org_alfresco_module_rm.action.dm; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.module.org_alfresco_module_rm.record.RecordService; +import org.alfresco.repo.action.executer.ActionExecuterAbstractBase; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.action.ParameterDefinition; +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.OwnableService; +import org.alfresco.service.namespace.QName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.surf.util.I18NUtil; + +public class DeclareRecordAction extends ActionExecuterAbstractBase implements RecordsManagementModel +{ + /** I18N */ + private static final String MSG_UNDECLARED_ONLY_RECORDS = "rm.action.undeclared-only-records"; + private static final String MSG_NO_DECLARE_MAND_PROP = "rm.action.no-declare-mand-prop"; + + /** Logger */ + private static Log logger = LogFactory.getLog(DeclareRecordAction.class); + + /** Record service */ + private RecordService recordService; + + /** Record management service */ + private RecordsManagementService recordsManagementService; + + /** Node service */ + private NodeService nodeService; + + /** Ownable service **/ + private OwnableService ownableService; + + /** Dictionary service */ + private DictionaryService dictionaryService; + + /** + * @param recordService record service + */ + public void setRecordService(RecordService recordService) + { + this.recordService = recordService; + } + + /** + * @param recordsManagementService records management service + */ + public void setRecordsManagementService( + RecordsManagementService recordsManagementService) + { + this.recordsManagementService = recordsManagementService; + } + + /** + * @param nodeService node service + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + /** + * @param ownableSerice ownable serice + */ + public void setOwnableService(OwnableService ownableService) + { + this.ownableService = ownableService; + } + + /** + * @param dictionaryService dictionary service + */ + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + @Override + protected void executeImpl(Action action, final NodeRef actionedUponNodeRef) + { + if (recordService.isRecord(actionedUponNodeRef) == true) + { + if (recordService.isDeclared(actionedUponNodeRef) == false) + { + List missingProperties = new ArrayList(5); + // Aspect not already defined - check mandatory properties then add + if (mandatoryPropertiesSet(actionedUponNodeRef, missingProperties) == true) + { + // Add the declared aspect + Map declaredProps = new HashMap(2); + declaredProps.put(PROP_DECLARED_AT, new Date()); + declaredProps.put(PROP_DECLARED_BY, AuthenticationUtil.getRunAsUser()); + nodeService.addAspect(actionedUponNodeRef, ASPECT_DECLARED_RECORD, declaredProps); + + // remove all owner related rights + ownableService.setOwner(actionedUponNodeRef, OwnableService.NO_OWNER); + } + else + { + throw new AlfrescoRuntimeException(buildMissingPropertiesErrorString(missingProperties)); + } + } + } + else + { + throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_UNDECLARED_ONLY_RECORDS, actionedUponNodeRef.toString())); + } + } + + private String buildMissingPropertiesErrorString(List missingProperties) + { + StringBuilder builder = new StringBuilder(255); + builder.append(I18NUtil.getMessage(MSG_NO_DECLARE_MAND_PROP)); + builder.append(" "); + for (String missingProperty : missingProperties) + { + builder.append(missingProperty) + .append(", "); + } + return builder.toString(); + } + + /** + * Helper method to check whether all the mandatory properties of the node have been set + * + * @param nodeRef + * node reference + * @return boolean true if all mandatory properties are set, false otherwise + */ + private boolean mandatoryPropertiesSet(NodeRef nodeRef, List missingProperties) + { + boolean result = true; + + Map nodeRefProps = nodeService.getProperties(nodeRef); + + QName nodeRefType = nodeService.getType(nodeRef); + + TypeDefinition typeDef = dictionaryService.getType(nodeRefType); + for (PropertyDefinition propDef : typeDef.getProperties().values()) + { + if (propDef.isMandatory() == true) + { + if (nodeRefProps.get(propDef.getName()) == null) + { + logMissingProperty(propDef, missingProperties); + + result = false; + break; + } + } + } + + if (result != false) + { + Set aspects = this.nodeService.getAspects(nodeRef); + for (QName aspect : aspects) + { + AspectDefinition aspectDef = dictionaryService.getAspect(aspect); + for (PropertyDefinition propDef : aspectDef.getProperties().values()) + { + if (propDef.isMandatory() == true) + { + if (nodeRefProps.get(propDef.getName()) == null) + { + logMissingProperty(propDef, missingProperties); + + result = false; + break; + } + } + } + } + } + + return result; + } + + /** + * Log information about missing properties. + * + * @param propDef property definition + * @param missingProperties missing properties + */ + private void logMissingProperty(PropertyDefinition propDef, List missingProperties) + { + if (logger.isWarnEnabled()) + { + StringBuilder msg = new StringBuilder(); + msg.append("Mandatory property missing: ").append(propDef.getName()); + logger.warn(msg.toString()); + } + missingProperties.add(propDef.getName().toString()); + } + + @Override + protected void addParameterDefinitions(List paramList) + { + // No parameters + } + +} \ No newline at end of file diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/FileRecordAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/FileRecordAction.java new file mode 100644 index 0000000000..62c9242f15 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/FileRecordAction.java @@ -0,0 +1,70 @@ +package org.alfresco.module.org_alfresco_module_rm.action.dm; + +import java.util.List; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.action.ParameterDefinitionImpl; +import org.alfresco.repo.action.executer.ActionExecuterAbstractBase; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.action.ParameterDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.model.FileNotFoundException; +import org.alfresco.service.cmr.repository.NodeRef; + +public class FileRecordAction extends ActionExecuterAbstractBase +{ + public static final String NAME = "file-record"; + public static final String PARAM_DESTINATION_RECORD_FOLDER = "destination-record-folder"; + + /** + * FileFolder service + */ + private FileFolderService fileFolderService; + + public void setFileFolderService(FileFolderService fileFolderService) + { + this.fileFolderService = fileFolderService; + } + + @Override + protected void addParameterDefinitions(List paramList) + { + paramList.add(new ParameterDefinitionImpl( + PARAM_DESTINATION_RECORD_FOLDER, + DataTypeDefinition.NODE_REF, + true, + getParamDisplayLabel(PARAM_DESTINATION_RECORD_FOLDER))); + } + + /** + * @see org.alfresco.repo.action.executer.ActionExecuter#execute(org.alfresco.repo.ref.NodeRef, org.alfresco.repo.ref.NodeRef) + */ + public void executeImpl(final Action ruleAction, final NodeRef actionedUponNodeRef) + { + final NodeRef destinationParent = (NodeRef)ruleAction.getParameterValue(PARAM_DESTINATION_RECORD_FOLDER); + + AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public Void doWork() throws Exception + { + try + { + fileFolderService.move(actionedUponNodeRef, destinationParent, null); + } + catch (FileNotFoundException e) + { + throw new AlfrescoRuntimeException("Could not file record.", e); + } + + return null; + } + + }); + + + } +} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/SplitEmailAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/SplitEmailAction.java index 9523e21558..75152018ac 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/SplitEmailAction.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/SplitEmailAction.java @@ -114,7 +114,7 @@ public class SplitEmailAction extends RMActionExecuterAbstractBase if (recordsManagementService.isRecord(actionedUponNodeRef) == true) { - if (recordsManagementService.isRecordDeclared(actionedUponNodeRef) == false) + if (recordService.isDeclared(actionedUponNodeRef) == false) { ChildAssociationRef parent = nodeService.getPrimaryParent(actionedUponNodeRef); @@ -175,7 +175,7 @@ public class SplitEmailAction extends RMActionExecuterAbstractBase { if (recordsManagementService.isRecord(filePlanComponent) == true) { - if (recordsManagementService.isRecordDeclared(filePlanComponent)) + if (recordService.isDeclared(filePlanComponent)) { if (throwException) { diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/UndeclareRecordAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/UndeclareRecordAction.java index a2a926f22d..bbf53afd2b 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/UndeclareRecordAction.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/UndeclareRecordAction.java @@ -48,7 +48,7 @@ public class UndeclareRecordAction extends RMActionExecuterAbstractBase { if (recordsManagementService.isRecord(actionedUponNodeRef) == true) { - if (recordsManagementService.isRecordDeclared(actionedUponNodeRef) == true) + if (recordService.isDeclared(actionedUponNodeRef) == true) { // Remove the declared aspect this.nodeService.removeAspect(actionedUponNodeRef, ASPECT_DECLARED_RECORD); @@ -73,7 +73,7 @@ public class UndeclareRecordAction extends RMActionExecuterAbstractBase { if (recordsManagementService.isRecord(filePlanComponent) == true) { - if (recordsManagementService.isRecordDeclared(filePlanComponent) == true) + if (recordService.isDeclared(filePlanComponent) == true) { return true; } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMActionProxyFactoryBean.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMActionProxyFactoryBean.java index 5470a46f85..ab3b1f5a9a 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMActionProxyFactoryBean.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMActionProxyFactoryBean.java @@ -18,6 +18,7 @@ */ package org.alfresco.module.org_alfresco_module_rm.capability; +import org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase; import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction; import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementActionService; import org.alfresco.repo.action.RuntimeActionService; @@ -59,7 +60,10 @@ public class RMActionProxyFactoryBean extends ProxyFactoryBean { public Void doWork() throws Exception { - runtimeActionService.registerActionExecuter((ActionExecuter) getObject()); + if (((RMActionExecuterAbstractBase)getTargetSource().getTarget()).isPublicAction() == true) + { + runtimeActionService.registerActionExecuter((ActionExecuter) getObject()); + } recordsManagementActionService.register((RecordsManagementAction) getObject()); return null; } 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 1d20f359fa..6f24815db7 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 @@ -61,6 +61,9 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; +/** + * RM After Invocation Provider + */ public class RMAfterInvocationProvider extends RMSecurityCommon implements AfterInvocationProvider, InitializingBean { diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMSecurityCommon.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMSecurityCommon.java index c80837debf..756faefff9 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMSecurityCommon.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMSecurityCommon.java @@ -22,7 +22,7 @@ import net.sf.acegisecurity.vote.AccessDecisionVoter; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; import org.alfresco.module.org_alfresco_module_rm.caveat.RMCaveatConfigComponent; -import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.transaction.AlfrescoTransactionSupport; import org.alfresco.service.cmr.repository.NodeRef; @@ -31,6 +31,9 @@ import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.PermissionService; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; /** * @author Roy Wetherall @@ -42,6 +45,8 @@ public class RMSecurityCommon private static Log logger = LogFactory.getLog(RMSecurityCommon.class); + private ApplicationContext applicationContext; + protected NodeService nodeService; protected PermissionService permissionService; protected RecordsManagementService rmService; diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/AbstractCapabilityCondition.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/AbstractCapabilityCondition.java index 5ace4d7a7e..4d8e8fbc5e 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/AbstractCapabilityCondition.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/AbstractCapabilityCondition.java @@ -21,6 +21,7 @@ package org.alfresco.module.org_alfresco_module_rm.capability.declarative; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; import org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.PermissionService; import org.springframework.beans.factory.BeanNameAware; @@ -39,6 +40,7 @@ public abstract class AbstractCapabilityCondition implements CapabilityCondition /** Services */ protected RecordsManagementService rmService; + protected RecordService recordService; protected PermissionService permissionService; protected NodeService nodeService; protected FreezeService freezeService; @@ -51,6 +53,14 @@ public abstract class AbstractCapabilityCondition implements CapabilityCondition this.rmService = rmService; } + /** + * @param recordService record service + */ + public void setRecordService(RecordService recordService) + { + this.recordService = recordService; + } + /** * @param permissionService permission service */ diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/DeclarativeCapability.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/DeclarativeCapability.java index f57f054423..e26954d6ca 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/DeclarativeCapability.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/DeclarativeCapability.java @@ -128,6 +128,9 @@ public class DeclarativeCapability extends AbstractCapability this.isUndetermined = isUndetermined; } + /** + * @return + */ public boolean isUndetermined() { return isUndetermined; diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/condition/DeclaredCapabilityCondition.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/condition/DeclaredCapabilityCondition.java index b57801aab4..f3f479095c 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/condition/DeclaredCapabilityCondition.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/condition/DeclaredCapabilityCondition.java @@ -33,7 +33,7 @@ public class DeclaredCapabilityCondition extends AbstractCapabilityCondition boolean result = false; if (FilePlanComponentKind.RECORD.equals(rmService.getFilePlanComponentKind(nodeRef)) == true) { - result = rmService.isRecordDeclared(nodeRef); + result = recordService.isDeclared(nodeRef); } return result; } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/impl/CreateCapability.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/impl/CreateCapability.java index a54bda2968..c606f4a7b7 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/impl/CreateCapability.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/impl/CreateCapability.java @@ -26,6 +26,7 @@ import net.sf.acegisecurity.vote.AccessDecisionVoter; import org.alfresco.model.ContentModel; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.capability.declarative.DeclarativeCapability; +import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.namespace.QName; @@ -37,6 +38,13 @@ import org.alfresco.service.namespace.QName; */ public class CreateCapability extends DeclarativeCapability { + private RecordService recordService; + + public void setRecordService(RecordService recordService) + { + this.recordService = recordService; + } + /** * @see org.alfresco.module.org_alfresco_module_rm.capability.Capability#evaluate(org.alfresco.service.cmr.repository.NodeRef) */ @@ -70,7 +78,7 @@ public class CreateCapability extends DeclarativeCapability { if(linkee == null) { - if(rmService.isRecord(destination) && rmService.isRecordDeclared(destination) == false) + if(rmService.isRecord(destination) && recordService.isDeclared(destination) == false) { if (permissionService.hasPermission(destination, RMPermissionModel.FILE_RECORDS) == AccessStatus.ALLOWED) { @@ -80,7 +88,7 @@ public class CreateCapability extends DeclarativeCapability } else { - if(rmService.isRecord(linkee) && rmService.isRecord(destination) && rmService.isRecordDeclared(destination) == false) + if(rmService.isRecord(linkee) && rmService.isRecord(destination) && recordService.isDeclared(destination) == false) { if (permissionService.hasPermission(destination, RMPermissionModel.FILE_RECORDS) == AccessStatus.ALLOWED) { diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/dataset/DataSetServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/dataset/DataSetServiceImpl.java index 3ad02aa34a..d7ba5dbf28 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/dataset/DataSetServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/dataset/DataSetServiceImpl.java @@ -9,8 +9,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; +import java.util.Map.Entry; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; @@ -20,7 +20,7 @@ import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; -import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementSearchBehaviour; +import org.alfresco.module.org_alfresco_module_rm.model.behaviour.RecordsManagementSearchBehaviour; import org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService; import org.alfresco.module.org_alfresco_module_rm.security.Role; import org.alfresco.repo.security.authentication.AuthenticationUtil; diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/forms/RecordsManagementFormFilter.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/forms/RecordsManagementFormFilter.java index 7b6579f5d8..5768888b3c 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/forms/RecordsManagementFormFilter.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/forms/RecordsManagementFormFilter.java @@ -25,6 +25,7 @@ import java.util.Map; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementAdminService; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementServiceRegistry; +import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.repo.forms.Field; import org.alfresco.repo.forms.FieldGroup; import org.alfresco.repo.forms.Form; @@ -58,6 +59,7 @@ public abstract class RecordsManagementFormFilter extends AbstractFilt protected RecordsManagementServiceRegistry rmServiceRegistry; protected RecordsManagementService rmService; protected RecordsManagementAdminService rmAdminService; + protected RecordService recordService; /** * Sets the NamespaceService instance @@ -109,6 +111,14 @@ public abstract class RecordsManagementFormFilter extends AbstractFilt this.rmAdminService = rmAdminService; } + /** + * @param recordService record service + */ + public void setRecordService(RecordService recordService) + { + this.recordService = recordService; + } + /** * Add property fields to group * diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/forms/RecordsManagementNodeFormFilter.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/forms/RecordsManagementNodeFormFilter.java index 420c6eccec..296515b7a9 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/forms/RecordsManagementNodeFormFilter.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/forms/RecordsManagementNodeFormFilter.java @@ -167,7 +167,7 @@ public class RecordsManagementNodeFormFilter extends RecordsManagementFormFilter protected void addRecordMetadataPropertyFieldsToGroup(Form form, NodeRef nodeRef) { - Set aspects = rmService.getRecordMetaDataAspects(); + Set aspects = recordService.getRecordMetaDataAspects(); for (QName aspect : aspects) { @@ -215,7 +215,7 @@ public class RecordsManagementNodeFormFilter extends RecordsManagementFormFilter { if (rmService.isRecord(nodeRef) == true) { - addTransientPropertyField(form, TRANSIENT_DECLARED, DataTypeDefinition.BOOLEAN, rmService.isRecordDeclared(nodeRef)); + addTransientPropertyField(form, TRANSIENT_DECLARED, DataTypeDefinition.BOOLEAN, recordService.isDeclared(nodeRef)); } DispositionSchedule ds = dispositionService.getDispositionSchedule(nodeRef); diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/identifier/IdentifierServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/identifier/IdentifierServiceImpl.java index e9d99efd5f..148865d15b 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/identifier/IdentifierServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/identifier/IdentifierServiceImpl.java @@ -120,7 +120,7 @@ public class IdentifierServiceImpl implements IdentifierService } /** - * Generate an identifier for a given type of object with the acompanying context. + * Generate an identifier for a given type of object with the accompanying context. * * @param type content type * @param context context diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/BaseEvaluator.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/BaseEvaluator.java index a99ca3c036..c8302ffa1c 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/BaseEvaluator.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/BaseEvaluator.java @@ -29,6 +29,7 @@ import org.alfresco.module.org_alfresco_module_rm.capability.Capability; import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService; import org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.AccessStatus; @@ -50,6 +51,9 @@ public abstract class BaseEvaluator implements RecordsManagementModel /** Records management service */ protected RecordsManagementService recordsManagementService; + /** Record service */ + protected RecordService recordService; + /** Node service */ protected NodeService nodeService; @@ -84,6 +88,14 @@ public abstract class BaseEvaluator implements RecordsManagementModel this.recordsManagementService = recordsManagementService; } + /** + * @param recordService record service + */ + public void setRecordService(RecordService recordService) + { + this.recordService = recordService; + } + /** * @param nodeService node service */ diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java index 29f526faa2..fce108024a 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java @@ -25,6 +25,7 @@ import org.alfresco.module.org_alfresco_module_rm.FilePlanComponentKind; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; +import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.security.AccessStatus; @@ -41,6 +42,9 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JSONC /** Records management service */ private RecordsManagementService recordsManagementService; + /** Record service */ + private RecordService recordService; + /** Capability service */ private CapabilityService capabilityService; @@ -56,7 +60,15 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JSONC public void setRecordsManagementService(RecordsManagementService recordsManagementService) { this.recordsManagementService = recordsManagementService; - } + } + + /** + * @param recordService record service + */ + public void setRecordService(RecordService recordService) + { + this.recordService = recordService; + } /** * @param capabilityService capability service @@ -128,7 +140,11 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JSONC rmNodeValues.put("kind", kind.toString()); // File plan node reference - rmNodeValues.put("filePlan", recordsManagementService.getFilePlan(nodeRef).toString()); + NodeRef filePlan = recordsManagementService.getFilePlan(nodeRef); + rmNodeValues.put("filePlan", filePlan.toString()); + + // Unfiled container node reference + rmNodeValues.put("unfiledRecordContainer", recordService.getUnfiledRecordContainer(filePlan).toString()); // Set the indicators array setIndicators(rmNodeValues, nodeRef); @@ -219,7 +235,7 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JSONC } else { - if (recordsManagementService.isRecordDeclared(nodeRef) == true) + if (recordService.isDeclared(nodeRef) == true) { result = "record"; } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/MultiParentEvaluator.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/MultiParentEvaluator.java index 805a082711..a90b49c491 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/MultiParentEvaluator.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/MultiParentEvaluator.java @@ -22,19 +22,39 @@ import java.util.List; import org.alfresco.model.ContentModel; import org.alfresco.module.org_alfresco_module_rm.jscript.app.BaseEvaluator; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.RegexQNamePattern; /** + * Determines whether a node has multiple parents within a file plan + * * @author Roy Wetherall */ public class MultiParentEvaluator extends BaseEvaluator { @Override - protected boolean evaluateImpl(NodeRef nodeRef) - { - List parents = nodeService.getParentAssocs(nodeRef, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL); - return (parents.size() > 1); + protected boolean evaluateImpl(final NodeRef nodeRef) + { + return AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public Boolean doWork() throws Exception + { + List parents = nodeService.getParentAssocs(nodeRef, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL); + int count = 0; + for (ChildAssociationRef parent : parents) + { + if (nodeService.hasAspect(parent.getParentRef(), ASPECT_FILE_PLAN_COMPONENT) == true) + { + count++; + } + } + + return (count > 1); + } + }); } } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/SplitEmailActionEvaluator.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/SplitEmailActionEvaluator.java index c28f1ae23b..574da9ed1e 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/SplitEmailActionEvaluator.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/SplitEmailActionEvaluator.java @@ -35,7 +35,7 @@ public class SplitEmailActionEvaluator extends BaseEvaluator protected boolean evaluateImpl(NodeRef nodeRef) { boolean result = false; - if (recordsManagementService.isRecordDeclared(nodeRef) == false) + if (recordService.isDeclared(nodeRef) == false) { ContentData contentData = (ContentData)nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT); if (contentData != null) 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 e8e3111ea2..a547203692 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 @@ -231,4 +231,5 @@ public interface RecordsManagementModel extends RecordsManagementCustomModel // Extended readers aspect public static final QName ASPECT_EXTENDED_READERS = QName.createQName(RM_URI, "extendedReaders"); public static final QName PROP_READERS = QName.createQName(RM_URI, "readers"); + } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/FilePlanComponentAspect.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/FilePlanComponentAspect.java similarity index 95% rename from rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/FilePlanComponentAspect.java rename to rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/FilePlanComponentAspect.java index 637f0caa4d..dae35c2349 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/FilePlanComponentAspect.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/FilePlanComponentAspect.java @@ -16,12 +16,13 @@ * 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.model; +package org.alfresco.module.org_alfresco_module_rm.model.behaviour; import java.io.Serializable; import java.util.Map; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.repo.copy.AbstractCopyBehaviourCallback; import org.alfresco.repo.copy.CopyBehaviourCallback; import org.alfresco.repo.copy.CopyDetails; diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/FilePlanType.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/FilePlanType.java new file mode 100644 index 0000000000..350e2ea7a9 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/FilePlanType.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2005-2011 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.model.behaviour; + +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.repo.node.NodeServicePolicies; +import org.alfresco.repo.policy.PolicyComponent; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.PermissionService; + +/** + * Behaviour associated with the file plan type + * + * @author Roy Wetherall + */ +public class FilePlanType implements RecordsManagementModel, + NodeServicePolicies.OnCreateNodePolicy +{ + /** Policy component */ + private PolicyComponent policyComponent; + + /** Node service */ + private NodeService nodeService; + + /** Permission service */ + private PermissionService permissionService; + + /** New record container name */ + private static final String NAME_NR_CONTAINER = "New Records"; + + /** + * Set the policy component + * @param policyComponent policy component + */ + public void setPolicyComponent(PolicyComponent policyComponent) + { + this.policyComponent = policyComponent; + } + + /** + * Set node service + * @param nodeService node service + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setPermissionService(PermissionService permissionService) + { + this.permissionService = permissionService; + } + + /** + * Bean initialisation method + */ + public void init() + { + // policyComponent.bindClassBehaviour( + // NodeServicePolicies.OnCreateNodePolicy.QNAME, + // TYPE_FILE_PLAN, + // new JavaBehaviour(this, "onCreateNode", NotificationFrequency.TRANSACTION_COMMIT)); + } + + /** + * @see org.alfresco.repo.node.NodeServicePolicies.OnCreateNodePolicy#onCreateNode(org.alfresco.service.cmr.repository.ChildAssociationRef) + */ + @Override + public void onCreateNode(ChildAssociationRef assoc) + { + // TODO refactor the file plan behaviours from the service code + } +} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordComponentIdentifierAspect.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordComponentIdentifierAspect.java similarity index 95% rename from rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordComponentIdentifierAspect.java rename to rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordComponentIdentifierAspect.java index 2a037bf81c..97e3b434a4 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordComponentIdentifierAspect.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordComponentIdentifierAspect.java @@ -16,11 +16,12 @@ * 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.model; +package org.alfresco.module.org_alfresco_module_rm.model.behaviour; import java.io.Serializable; import java.util.Map; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy; import org.alfresco.repo.node.NodeServicePolicies.OnUpdatePropertiesPolicy; diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordContainerType.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordContainerType.java similarity index 95% rename from rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordContainerType.java rename to rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordContainerType.java index 5bd85b7f1e..d4117ea00b 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordContainerType.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordContainerType.java @@ -16,11 +16,12 @@ * 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.model; +package org.alfresco.module.org_alfresco_module_rm.model.behaviour; import org.alfresco.model.ContentModel; import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementActionService; import org.alfresco.module.org_alfresco_module_rm.identifier.IdentifierService; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.PolicyComponent; diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordCopyBehaviours.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordCopyBehaviours.java similarity index 95% rename from rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordCopyBehaviours.java rename to rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordCopyBehaviours.java index 7c4377c9d0..c58cca1a05 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordCopyBehaviours.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordCopyBehaviours.java @@ -16,7 +16,7 @@ * 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.model; +package org.alfresco.module.org_alfresco_module_rm.model.behaviour; import java.io.Serializable; import java.util.ArrayList; @@ -26,6 +26,7 @@ import java.util.Map; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementServiceRegistry; import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementActionService; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.repo.copy.AbstractCopyBehaviourCallback; import org.alfresco.repo.copy.CopyBehaviourCallback; import org.alfresco.repo.copy.CopyDetails; diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementSearchBehaviour.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordsManagementSearchBehaviour.java similarity index 92% rename from rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementSearchBehaviour.java rename to rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordsManagementSearchBehaviour.java index 79823d13a7..84adf52828 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementSearchBehaviour.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordsManagementSearchBehaviour.java @@ -16,7 +16,7 @@ * 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.model; +package org.alfresco.module.org_alfresco_module_rm.model.behaviour; import java.io.Serializable; import java.util.ArrayList; @@ -36,6 +36,7 @@ import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedul import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionScheduleImpl; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService; import org.alfresco.module.org_alfresco_module_rm.event.EventCompletionDetails; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.vital.VitalRecordDefinition; import org.alfresco.module.org_alfresco_module_rm.vital.VitalRecordService; import org.alfresco.repo.policy.JavaBehaviour; @@ -315,13 +316,22 @@ public class RecordsManagementSearchBehaviour implements RecordsManagementModel } } - public void onAddRecordAspect(NodeRef nodeRef, QName aspectTypeQName) + public void onAddRecordAspect(final NodeRef nodeRef, final QName aspectTypeQName) { - if (nodeService.exists(nodeRef) == true) + AuthenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork() { - applySearchAspect(nodeRef); - setupDispositionScheduleProperties(nodeRef); - } + @Override + public Void doWork() throws Exception + { + if (nodeService.exists(nodeRef) == true) + { + applySearchAspect(nodeRef); + setupDispositionScheduleProperties(nodeRef); + } + + return null; + } + }); } public void recordFolderCreate(ChildAssociationRef childAssocRef) @@ -494,20 +504,28 @@ public class RecordsManagementSearchBehaviour implements RecordsManagementModel } } - public void rmSearchAspectAdd(NodeRef nodeRef, QName aspectTypeQName) - { - if (nodeService.exists(nodeRef) == true) + public void rmSearchAspectAdd(final NodeRef nodeRef, final QName aspectTypeQName) + { + AuthenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork() { - // Initialise the search parameters as required - setVitalRecordDefintionDetails(nodeRef); - } + @Override + public Void doWork() throws Exception + { + if (nodeService.exists(nodeRef) == true) + { + // Initialise the search parameteres as required + setVitalRecordDefintionDetails(nodeRef); + } + + return null; + } + }); } public void vitalRecordDefintionAddAspect(NodeRef nodeRef, QName aspectTypeQName) { - // Only care about record folders or record categories - if (recordsManagementService.isRecordFolder(nodeRef) == true || - recordsManagementService.isRecordCategory(nodeRef) == true) + // Only care about record folders + if (recordsManagementService.isRecordFolder(nodeRef) == true) { updateVitalRecordDefinitionValues(nodeRef); } @@ -515,9 +533,8 @@ public class RecordsManagementSearchBehaviour implements RecordsManagementModel public void vitalRecordDefintionUpdateProperties(NodeRef nodeRef, Map before, Map after) { - // Only care about record folders or record categories - if (recordsManagementService.isRecordFolder(nodeRef) == true || - recordsManagementService.isRecordCategory(nodeRef) == true) + // Only care about record folders + if (recordsManagementService.isRecordFolder(nodeRef) == true) { Set props = new HashSet(1); props.add(PROP_REVIEW_PERIOD); @@ -537,17 +554,14 @@ public class RecordsManagementSearchBehaviour implements RecordsManagementModel applySearchAspect(nodeRef); setVitalRecordDefintionDetails(nodeRef); - if (recordsManagementService.isRecordFolder(nodeRef) == true) - { - List records = recordsManagementService.getRecords(nodeRef); - for (NodeRef record : records) - { - // Apply the search aspect - applySearchAspect(record); - - // Set the vital record definition details - setVitalRecordDefintionDetails(record); - } + List records = recordsManagementService.getRecords(nodeRef); + for (NodeRef record : records) + { + // Apply the search aspect + applySearchAspect(record); + + // Set the vital record definition details + setVitalRecordDefintionDetails(record); } } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RmSiteType.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RmSiteType.java similarity index 66% rename from rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RmSiteType.java rename to rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RmSiteType.java index 8224640d20..51a0ea48de 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RmSiteType.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RmSiteType.java @@ -16,8 +16,9 @@ * 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.model; +package org.alfresco.module.org_alfresco_module_rm.model.behaviour; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.search.RecordsManagementSearchService; import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.policy.JavaBehaviour; @@ -55,6 +56,9 @@ public class RmSiteType implements RecordsManagementModel, /** Record Management Search Service */ private RecordsManagementSearchService recordsManagementSearchService; + /** Behaviour */ + JavaBehaviour behaviour = new JavaBehaviour(this, "onCreateNode", NotificationFrequency.FIRST_EVENT); + /** * Set the policy component * @param policyComponent policy component @@ -98,7 +102,7 @@ public class RmSiteType implements RecordsManagementModel, policyComponent.bindClassBehaviour( NodeServicePolicies.OnCreateNodePolicy.QNAME, TYPE_RM_SITE, - new JavaBehaviour(this, "onCreateNode", NotificationFrequency.FIRST_EVENT)); + behaviour); } /** @@ -107,33 +111,41 @@ public class RmSiteType implements RecordsManagementModel, @Override public void onCreateNode(ChildAssociationRef childAssocRef) { - final NodeRef rmSite = childAssocRef.getChildRef(); - - // Do not execute behaviour if this has been created in the archive store - if(rmSite.getStoreRef().equals(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE) == true) - { - // This is not the spaces store - probably the archive store - return; - } - - if (nodeService.exists(rmSite) == true) - { - AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() + behaviour.disable(); + try + { + final NodeRef rmSite = childAssocRef.getChildRef(); + + // Do not execute behaviour if this has been created in the archive store + if(rmSite.getStoreRef().equals(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE) == true) { - public Object doWork() + // This is not the spaces store - probably the archive store + return; + } + + if (nodeService.exists(rmSite) == true) + { + AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() { - SiteInfo siteInfo = siteService.getSite(rmSite); - if (siteInfo != null) - { - // Create the file plan component - siteService.createContainer(siteInfo.getShortName(), COMPONENT_DOCUMENT_LIBRARY, TYPE_FILE_PLAN, null); - - // Add the reports - recordsManagementSearchService.addReports(siteInfo.getShortName()); - } - return null; - } - }, AuthenticationUtil.getAdminUserName()); - } + public Object doWork() + { + SiteInfo siteInfo = siteService.getSite(rmSite); + if (siteInfo != null) + { + // Create the file plan component + siteService.createContainer(siteInfo.getShortName(), COMPONENT_DOCUMENT_LIBRARY, TYPE_FILE_PLAN, null); + + // Add the reports + recordsManagementSearchService.addReports(siteInfo.getShortName()); + } + return null; + } + }, AuthenticationUtil.getAdminUserName()); + } + } + finally + { + behaviour.enable(); + } } } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/ScheduledAspect.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/ScheduledAspect.java similarity index 92% rename from rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/ScheduledAspect.java rename to rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/ScheduledAspect.java index 22169f0417..c4e1c004ed 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/ScheduledAspect.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/ScheduledAspect.java @@ -16,9 +16,10 @@ * 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.model; +package org.alfresco.module.org_alfresco_module_rm.model.behaviour; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.PolicyComponent; diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/permission/OtherImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/permission/OtherImpl.java deleted file mode 100644 index 958d67566a..0000000000 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/permission/OtherImpl.java +++ /dev/null @@ -1,370 +0,0 @@ -package org.alfresco.module.org_alfresco_module_rm.permission; - -import java.io.Serializable; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.Set; - -import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; -import org.alfresco.repo.cache.SimpleCache; -import org.alfresco.repo.domain.permissions.AclDAO; -import org.alfresco.repo.security.permissions.AccessControlEntry; -import org.alfresco.repo.security.permissions.AccessControlList; -import org.alfresco.repo.security.permissions.PermissionEntry; -import org.alfresco.repo.security.permissions.PermissionReference; -import org.alfresco.repo.security.permissions.impl.ModelDAO; -import org.alfresco.repo.security.permissions.impl.PermissionServiceImpl; -import org.alfresco.repo.security.permissions.impl.RequiredPermission; -import org.alfresco.repo.security.permissions.impl.SimplePermissionReference; -import org.alfresco.service.cmr.security.AccessStatus; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.namespace.QName; -import org.alfresco.util.Pair; - -public class OtherImpl extends PermissionServiceImpl -{ - static SimplePermissionReference RM_OLD_ALL_PERMISSIONS_REFERENCE = SimplePermissionReference.getPermissionReference( - QName.createQName("", PermissionService.ALL_PERMISSIONS), - PermissionService.ALL_PERMISSIONS); - - private SimpleCache> rmReadersCache; - - private AclDAO rmAclDaoComponent; - - private ModelDAO rmModelDao; - - public void setRmReadersCache(SimpleCache> rmReadersCache) - { - this.rmReadersCache = rmReadersCache; - } - - public void setRmAclDAO(AclDAO rmAclDaoComponent) - { - this.rmAclDaoComponent = rmAclDaoComponent; - } - - public void setRmModelDAO(ModelDAO rmModelDao) - { - this.rmModelDao = rmModelDao; - } - - @Override - public void setAnyDenyDenies(boolean anyDenyDenies) - { - super.setAnyDenyDenies(anyDenyDenies); - rmReadersCache.clear(); - } - - @Override - public Set getReaders(Long aclId) - { - Set dmReaders = super.getReaders(aclId); - - Set rmReaders = rmReadersCache.get(aclId); - if (rmReaders == null) - { - rmReaders = buildRMReaders(aclId); - rmReadersCache.put(aclId, rmReaders); - } - - Set result = new HashSet(); - result.addAll(dmReaders); - result.addAll(rmReaders); - return result; - } - - private Set buildRMReaders(Long aclId) - { - AccessControlList acl = rmAclDaoComponent.getAccessControlList(aclId); - if (acl == null) - { - return Collections.emptySet(); - } - - HashSet assigned = new HashSet(); - HashSet readers = new HashSet(); - - for (AccessControlEntry ace : acl.getEntries()) - { - assigned.add(ace.getAuthority()); - } - - PermissionReference permissionRef = getPermissionReference(RMPermissionModel.READ_RECORDS); - - for (String authority : assigned) - { - RMUnconditionalAclTest rmTest = new RMUnconditionalAclTest(permissionRef); - if (rmTest.evaluate(authority, aclId)) - { - readers.add(authority); - } - } - - return Collections.unmodifiableSet(readers); - } - - /** - * Ignores type and aspect requirements on the node - * - */ - private class RMUnconditionalAclTest - { - /* - * The required permission. - */ - PermissionReference required; - - /* - * Granters of the permission - */ - Set granters; - - /* - * The additional permissions required at the node level. - */ - Set nodeRequirements = new HashSet(); - - /* - * Constructor just gets the additional requirements - */ - RMUnconditionalAclTest(PermissionReference required) - { - this.required = required; - - // Set the required node permissions - if (required.equals(getPermissionReference(ALL_PERMISSIONS))) - { - nodeRequirements = rmModelDao.getUnconditionalRequiredPermissions(getPermissionReference(PermissionService.FULL_CONTROL), RequiredPermission.On.NODE); - } - else - { - nodeRequirements = rmModelDao.getUnconditionalRequiredPermissions(required, RequiredPermission.On.NODE); - } - - if (rmModelDao.getUnconditionalRequiredPermissions(required, RequiredPermission.On.PARENT).size() > 0) - { - throw new IllegalStateException("Parent permissions can not be checked for an acl"); - } - - if (rmModelDao.getUnconditionalRequiredPermissions(required, RequiredPermission.On.CHILDREN).size() > 0) - { - throw new IllegalStateException("Child permissions can not be checked for an acl"); - } - - // Find all the permissions that grant the allowed permission - // All permissions are treated specially. - granters = new LinkedHashSet(128, 1.0f); - granters.addAll(rmModelDao.getGrantingPermissions(required)); - granters.add(getAllPermissionReference()); - granters.add(RM_OLD_ALL_PERMISSIONS_REFERENCE); - } - - /** - * Internal hook point for recursion - * - * @param authorisations - * @param nodeRef - * @param denied - * @param recursiveIn - * @return true if granted - */ - boolean evaluate(String authority, Long aclId) - { - // Start out true and "and" all other results - boolean success = true; - - // Check the required permissions but not for sets they rely on - // their underlying permissions - //if (modelDAO.checkPermission(required)) - //{ - - // We have to do the test as no parent will help us out - success &= hasSinglePermission(authority, aclId); - - if (!success) - { - return false; - } - //} - - // Check the other permissions required on the node - for (PermissionReference pr : nodeRequirements) - { - // Build a new test - RMUnconditionalAclTest nt = new RMUnconditionalAclTest(pr); - success &= nt.evaluate(authority, aclId); - if (!success) - { - return false; - } - } - - return success; - } - - boolean hasSinglePermission(String authority, Long aclId) - { - // Check global permission - - if (checkGlobalPermissions(authority)) - { - return true; - } - - if(aclId == null) - { - return false; - } - else - { - return checkRequired(authority, aclId); - } - - } - - /** - * Check if we have a global permission - * - * @param authorisations - * @return true if granted - */ - private boolean checkGlobalPermissions(String authority) - { - for (PermissionEntry pe : rmModelDao.getGlobalPermissionEntries()) - { - if (isGranted(pe, authority)) - { - return true; - } - } - return false; - } - - /** - * Check that a given authentication is available on a node - * - * @param authorisations - * @param nodeRef - * @param denied - * @return true if a check is required - */ - boolean checkRequired(String authority, Long aclId) - { - AccessControlList acl = rmAclDaoComponent.getAccessControlList(aclId); - - if (acl == null) - { - return false; - } - - Set> denied = new HashSet>(); - - // Check if each permission allows - the first wins. - // We could have other voting style mechanisms here - for (AccessControlEntry ace : acl.getEntries()) - { - if (isGranted(ace, authority, denied)) - { - return true; - } - } - return false; - } - - /** - * Is a permission granted - * - * @param pe - - * the permissions entry to consider - * @param granters - - * the set of granters - * @param authorisations - - * the set of authorities - * @param denied - - * the set of denied permissions/authority pais - * @return true if granted - */ - private boolean isGranted(AccessControlEntry ace, String authority, Set> denied) - { - // If the permission entry denies then we just deny - if (ace.getAccessStatus() == AccessStatus.DENIED) - { - denied.add(new Pair(ace.getAuthority(), ace.getPermission())); - - Set granters = rmModelDao.getGrantingPermissions(ace.getPermission()); - for (PermissionReference granter : granters) - { - denied.add(new Pair(ace.getAuthority(), granter)); - } - - // All the things granted by this permission must be - // denied - Set grantees = rmModelDao.getGranteePermissions(ace.getPermission()); - for (PermissionReference grantee : grantees) - { - denied.add(new Pair(ace.getAuthority(), grantee)); - } - - // All permission excludes all permissions available for - // the node. - if (ace.getPermission().equals(getAllPermissionReference()) || ace.getPermission().equals(RM_OLD_ALL_PERMISSIONS_REFERENCE)) - { - for (PermissionReference deny : rmModelDao.getAllPermissions()) - { - denied.add(new Pair(ace.getAuthority(), deny)); - } - } - - return false; - } - - // The permission is allowed but we deny it as it is in the denied - // set - - if (denied != null) - { - Pair specific = new Pair(ace.getAuthority(), required); - if (denied.contains(specific)) - { - return false; - } - } - - // If the permission has a match in both the authorities and - // granters list it is allowed - // It applies to the current user and it is granted - if (authority.equals(ace.getAuthority()) && granters.contains(ace.getPermission())) - { - { - return true; - } - } - - // Default deny - return false; - } - - private boolean isGranted(PermissionEntry pe, String authority) - { - // If the permission entry denies then we just deny - if (pe.isDenied()) - { - return false; - } - - // If the permission has a match in both the authorities and - // granters list it is allowed - // It applies to the current user and it is granted - if (granters.contains(pe.getPermissionReference()) && authority.equals(pe.getAuthority())) - { - { - return true; - } - } - - // Default deny - return false; - } - } -} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/BootstrapTestDataGet.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/BootstrapTestDataGet.java index 20afd82928..3b27ca58ee 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/BootstrapTestDataGet.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/BootstrapTestDataGet.java @@ -33,8 +33,8 @@ import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; -import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementSearchBehaviour; -import org.alfresco.module.org_alfresco_module_rm.model.RmSiteType; +import org.alfresco.module.org_alfresco_module_rm.model.behaviour.RecordsManagementSearchBehaviour; +import org.alfresco.module.org_alfresco_module_rm.model.behaviour.RmSiteType; import org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService; import org.alfresco.module.org_alfresco_module_rm.security.Role; import org.alfresco.repo.security.authentication.AuthenticationUtil; diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/DataSetPost.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/DataSetPost.java index e8951ad495..19166820b8 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/DataSetPost.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/DataSetPost.java @@ -5,7 +5,7 @@ import java.util.Map; import org.alfresco.module.org_alfresco_module_rm.dataset.DataSetService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; -import org.alfresco.module.org_alfresco_module_rm.model.RmSiteType; +import org.alfresco.module.org_alfresco_module_rm.model.behaviour.RmSiteType; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.site.SiteService; import org.apache.commons.lang.StringUtils; diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/DataSetsGet.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/DataSetsGet.java index 1e3db12b9c..e36c88e53f 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/DataSetsGet.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/DataSetsGet.java @@ -7,7 +7,7 @@ import java.util.Map; import org.alfresco.module.org_alfresco_module_rm.dataset.DataSet; import org.alfresco.module.org_alfresco_module_rm.dataset.DataSetService; -import org.alfresco.module.org_alfresco_module_rm.model.RmSiteType; +import org.alfresco.module.org_alfresco_module_rm.model.behaviour.RmSiteType; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.site.SiteService; import org.apache.commons.lang.StringUtils; diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/ExportPost.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/ExportPost.java index b4b4c09303..38cb3daf17 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/ExportPost.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/ExportPost.java @@ -20,28 +20,28 @@ package org.alfresco.module.org_alfresco_module_rm.script; import java.io.File; import java.io.IOException; -import java.io.StringWriter; import java.io.PrintWriter; +import java.io.StringWriter; import org.alfresco.model.ContentModel; import org.alfresco.model.RenditionModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; -import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementSearchBehaviour; +import org.alfresco.module.org_alfresco_module_rm.model.behaviour.RecordsManagementSearchBehaviour; import org.alfresco.repo.exporter.ACPExportPackageHandler; import org.alfresco.repo.web.scripts.content.StreamACP; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.view.ExporterCrawlerParameters; import org.alfresco.service.cmr.view.Location; import org.alfresco.service.namespace.QName; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; /** * Creates an RM specific ACP file of nodes to export then streams it back diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/RecordMetaDataAspectsGet.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/RecordMetaDataAspectsGet.java index a15ac40173..bd826287ca 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/RecordMetaDataAspectsGet.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/RecordMetaDataAspectsGet.java @@ -24,7 +24,7 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; +import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.service.cmr.dictionary.AspectDefinition; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.namespace.NamespaceService; @@ -41,7 +41,7 @@ public class RecordMetaDataAspectsGet extends DeclarativeWebScript { protected DictionaryService dictionaryService; protected NamespaceService namespaceService; - protected RecordsManagementService recordsManagementService; + protected RecordService recordService; /** * Set the dictionary service instance @@ -62,10 +62,13 @@ public class RecordMetaDataAspectsGet extends DeclarativeWebScript { this.namespaceService = namespaceService; } - - public void setRecordsManagementService(RecordsManagementService recordsManagementService) + + /** + * @param recordService record service + */ + public void setRecordService(RecordService recordService) { - this.recordsManagementService = recordsManagementService; + this.recordService = recordService; } /* @@ -75,7 +78,7 @@ public class RecordMetaDataAspectsGet extends DeclarativeWebScript protected Map executeImpl(WebScriptRequest req, Status status, Cache cache) { // Get the details of all the aspects - Set aspectQNames = recordsManagementService.getRecordMetaDataAspects(); + Set aspectQNames = recordService.getRecordMetaDataAspects(); List> aspects = new ArrayList>(aspectQNames.size()+1); for (QName aspectQName : aspectQNames) { diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/TransferGet.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/TransferGet.java index 022ad7bbbe..c5f2b38716 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/TransferGet.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/TransferGet.java @@ -24,17 +24,17 @@ import java.io.IOException; import org.alfresco.model.ContentModel; import org.alfresco.model.RenditionModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; -import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementSearchBehaviour; +import org.alfresco.module.org_alfresco_module_rm.model.behaviour.RecordsManagementSearchBehaviour; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.view.ExporterCrawlerParameters; import org.alfresco.service.cmr.view.Location; import org.alfresco.service.namespace.QName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.extensions.webscripts.Cache; import org.springframework.extensions.webscripts.Status; import org.springframework.extensions.webscripts.WebScriptRequest; import org.springframework.extensions.webscripts.WebScriptResponse; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; /** * Streams the nodes of a transfer object to the client in the form of an diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RMSearchPropertiesGet.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RMSearchPropertiesGet.java index 8948cb0895..d97cc1a53e 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RMSearchPropertiesGet.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RMSearchPropertiesGet.java @@ -25,7 +25,7 @@ import java.util.Map; import java.util.Set; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementAdminService; -import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; +import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.service.cmr.dictionary.AspectDefinition; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.PropertyDefinition; @@ -43,35 +43,45 @@ import org.springframework.extensions.webscripts.WebScriptRequest; */ public class RMSearchPropertiesGet extends DeclarativeWebScript { - private RecordsManagementAdminService adminService; - - private RecordsManagementService recordsManagementService; - - private DictionaryService dictionaryService; - + /** Services */ + private RecordsManagementAdminService adminService; + private RecordService recordService; + private DictionaryService dictionaryService; private NamespaceService namespaceService; - + + /** + * @param adminService records management admin service + */ public void setAdminService(RecordsManagementAdminService adminService) { this.adminService = adminService; } - public void setRecordsManagementService(RecordsManagementService recordsManagementService) + /** + * @param recordService record service + */ + public void setRecordService(RecordService recordService) { - this.recordsManagementService = recordsManagementService; + this.recordService = recordService; } + /** + * @param dictionaryService dictionary service + */ public void setDictionaryService(DictionaryService dictionaryService) { this.dictionaryService = dictionaryService; } + /** + * @param namespaceService namespace service + */ public void setNamespaceService(NamespaceService namespaceService) { this.namespaceService = namespaceService; } - /* + /** * @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.Status, org.alfresco.web.scripts.Cache) */ @Override @@ -81,7 +91,7 @@ public class RMSearchPropertiesGet extends DeclarativeWebScript List groups = new ArrayList(5); - Set aspects = recordsManagementService.getRecordMetaDataAspects(); + Set aspects = recordService.getRecordMetaDataAspects(); for (QName aspect : aspects) { Map properties = dictionaryService.getPropertyDefs(aspect); diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityServiceImpl.java index 3a02d14040..362595feec 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityServiceImpl.java @@ -392,25 +392,25 @@ public class RecordsManagementSecurityServiceImpl implements RecordsManagementSe { public Object doWork() { - Set perms = permissionService.getAllSetPermissions(catNodeRef); - for (AccessPermission perm : perms) - { - if (ExtendedReaderDynamicAuthority.EXTENDED_READER.equals(perm.getAuthority()) == false) - { - AccessStatus accessStatus = perm.getAccessStatus(); - boolean allow = false; - if (AccessStatus.ALLOWED.equals(accessStatus) == true) - { - allow = true; - } - permissionService.setPermission( - folderNodeRef, - perm.getAuthority(), - perm.getPermission(), - allow); - } - } - + Set perms = permissionService.getAllSetPermissions(catNodeRef); + for (AccessPermission perm : perms) + { + if (ExtendedReaderDynamicAuthority.EXTENDED_READER.equals(perm.getAuthority()) == false) + { + AccessStatus accessStatus = perm.getAccessStatus(); + boolean allow = false; + if (AccessStatus.ALLOWED.equals(accessStatus) == true) + { + allow = true; + } + permissionService.setPermission( + folderNodeRef, + perm.getAuthority(), + perm.getPermission(), + allow); + } + } + return null; } }, AuthenticationUtil.getSystemUserName()); diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/NewRecordsManagementSecurityServiceImplTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/NewRecordsManagementSecurityServiceImplTest.java new file mode 100644 index 0000000000..938768a545 --- /dev/null +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/NewRecordsManagementSecurityServiceImplTest.java @@ -0,0 +1,151 @@ + +package org.alfresco.module.org_alfresco_module_rm.test.service; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * Records management security service test. + * + * @author Roy Wetherall + */ +public class NewRecordsManagementSecurityServiceImplTest extends BaseRMTestCase +{ + private NodeRef record; + private NodeRef recordToo; + + @Override + protected boolean isUserTest() + { + return true; + } + + @Override + protected void setupTestDataImpl() + { + super.setupTestDataImpl(); + + record = utils.createRecord(rmFolder, "record.txt"); + recordToo = utils.createRecord(rmFolder, "recordToo.txt"); + } + + + // TODO testGetProtectedAspects + + // TODO getProtectedProperties + + // TODO bootstrapDefaultRoles + + // TODO getRoles + + // TODO getRolesByUser + + // TODO getRole + + // TODO existsRole + + // TODO hasRMAdminRole + + // TODO createRole + + // TODO updateRole + + // TODO deleteRole + + // TODO assignRoleToAuthority + + // TODO setPermission + + // TODO deletePermission + + public void testExtendedReaders() + { + doTestInTransaction(new Test() + { + public Void run() + { + assertFalse(hasExtendedReadersAspect(filePlan)); + assertFalse(hasExtendedReadersAspect(rmContainer)); + assertFalse(hasExtendedReadersAspect(rmFolder)); + assertFalse(hasExtendedReadersAspect(record)); + + assertNull(securityService.getExtendedReaders(record)); + + Set extendedReaders = new HashSet(2); + extendedReaders.add("monkey"); + extendedReaders.add("elephant"); + + securityService.setExtendedReaders(record, extendedReaders); + + Map testMap = new HashMap(2); + testMap.put("monkey", Integer.valueOf(1)); + testMap.put("elephant", Integer.valueOf(1)); + + test(filePlan, testMap); + test(rmContainer, testMap); + test(rmFolder, testMap); + test(record, testMap); + + Set extendedReadersToo = new HashSet(2); + extendedReadersToo.add("monkey"); + extendedReadersToo.add("snake"); + + securityService.setExtendedReaders(recordToo, extendedReadersToo); + + Map testMapToo = new HashMap(2); + testMapToo.put("monkey", Integer.valueOf(1)); + testMapToo.put("snake", Integer.valueOf(1)); + + Map testMapThree = new HashMap(3); + testMapThree.put("monkey", Integer.valueOf(2)); + testMapThree.put("elephant", Integer.valueOf(1)); + testMapThree.put("snake", Integer.valueOf(1)); + + test(filePlan, testMapThree); + test(rmContainer, testMapThree); + test(rmFolder, testMapThree); + test(recordToo, testMapToo); + + return null; + } + + private boolean hasExtendedReadersAspect(NodeRef nodeRef) + { + return nodeService.hasAspect(nodeRef, ASPECT_EXTENDED_READERS); + } + + private void test(NodeRef nodeRef, Map testMap) + { + assertTrue(hasExtendedReadersAspect(nodeRef)); + + Map readersMap = (Map)nodeService.getProperty(nodeRef, PROP_READERS); + assertNotNull(readersMap); + assertEquals(testMap.size(), readersMap.size()); + + for (Map.Entry entry: testMap.entrySet()) + { + assertTrue(readersMap.containsKey(entry.getKey())); + assertEquals(entry.getValue(), readersMap.get(entry.getKey())); + + } + + Set readers = securityService.getExtendedReaders(nodeRef); + assertNotNull(readers); + assertEquals(testMap.size(), readers.size()); + } + }); + } + + // TODO getExtendedReaders + + // TODO setExtendedReaders + + // TODO removeExtendedReaders + + // TODO removeAllExtendedReaders +} diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordServiceTestImpl.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordServiceTestImpl.java new file mode 100644 index 0000000000..9bd4d054bf --- /dev/null +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordServiceTestImpl.java @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2005-2011 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.service; + +import org.alfresco.model.ContentModel; +import org.alfresco.module.org_alfresco_module_rm.action.dm.CreateRecordAction; +import org.alfresco.module.org_alfresco_module_rm.capability.Capability; +import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; +import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority; +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.site.SiteModel; +import org.alfresco.repo.site.SiteServiceImpl; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.action.ActionService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.PermissionService; +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.util.GUID; + +/** + * Record service implementation unit test. + * + * @author Roy Wetherall + */ +public class RecordServiceTestImpl extends BaseRMTestCase +{ + protected static final String COLLABORATION_SITE_ID = "collab-site-id"; + + protected ActionService dmActionService; + protected TaggingService taggingService; + protected PermissionService dmPermissionService; + + protected SiteInfo collaborationSite; + protected NodeRef documentLibrary; + protected NodeRef dmFolder; + protected NodeRef dmDocument; + + protected String dmUserName; + protected NodeRef dmUserPerson; + + @Override + protected void initServices() + { + super.initServices(); + + dmActionService = (ActionService)applicationContext.getBean("ActionService"); + taggingService = (TaggingService)applicationContext.getBean("TaggingService"); + dmPermissionService = (PermissionService)applicationContext.getBean("PermissionService"); + } + + @Override + protected boolean isUserTest() + { + return true; + } + + @Override + protected void setupTestData() + { + super.setupTestData(); + + doTestInTransaction(new Test() + { + public Void run() + { + setupCollaborationSiteTestDataImpl(); + return null; + } + }, + AuthenticationUtil.getSystemUserName()); + } + + protected void setupCollaborationSiteTestDataImpl() + { + // create collaboration site + collaborationSite = siteService.createSite("preset", COLLABORATION_SITE_ID, "title", "description", SiteVisibility.PRIVATE); + documentLibrary = SiteServiceImpl.getSiteContainer( + COLLABORATION_SITE_ID, + SiteService.DOCUMENT_LIBRARY, + true, + siteService, + transactionService, + taggingService); + + assertNotNull("Collaboration site document library component was not successfully created.", documentLibrary); + + // create a folder and documents + dmFolder = fileFolderService.create(documentLibrary, "collabFolder", ContentModel.TYPE_FOLDER).getNodeRef(); + dmDocument = fileFolderService.create(dmFolder, "collabDocument.txt", ContentModel.TYPE_CONTENT).getNodeRef(); + } + + @Override + protected void setupTestUsersImpl(NodeRef filePlan) + { + super.setupTestUsersImpl(filePlan); + + dmUserName = GUID.generate(); + dmUserPerson = createPerson(dmUserName); + siteService.setMembership(COLLABORATION_SITE_ID, dmUserName, SiteModel.SITE_COLLABORATOR); + } + + @Override + protected void tearDownImpl() + { + super.tearDownImpl(); + siteService.deleteSite(COLLABORATION_SITE_ID); + } + + public void testCreateRecordAction() + { + doTestInTransaction(new Test() + { + public Void run() + { + assertEquals(AccessStatus.DENIED, dmPermissionService.hasPermission(dmDocument, RMPermissionModel.READ_RECORDS)); + assertEquals(AccessStatus.DENIED, dmPermissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS)); + + Action action = dmActionService.createAction(CreateRecordAction.NAME); + dmActionService.executeAction(action, dmDocument); + + return null; + } + + public void test(Void result) throws Exception + { + assertEquals(AccessStatus.ALLOWED, dmPermissionService.hasPermission(dmDocument, RMPermissionModel.READ_RECORDS)); + assertEquals(AccessStatus.ALLOWED, dmPermissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS)); + + assertTrue(rmService.isRecord(dmDocument)); + + // + Capability createCapability = capabilityService.getCapability("Create"); + assertNotNull(createCapability); + createCapability.evaluate(dmDocument); + + + + }; + }, + dmUserName); + + doTestInTransaction(new Test() + { + public Void run() + { + + return null; + } + }); + } + +} diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordsManagementSecurityServiceImplTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordsManagementSecurityServiceImplTest.java index 76838128a3..a1872523a8 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordsManagementSecurityServiceImplTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordsManagementSecurityServiceImplTest.java @@ -56,7 +56,7 @@ import org.alfresco.util.GUID; import org.alfresco.util.PropertyMap; /** - * Event service implementation unit test + * Security service implementation unit test * * @author Roy Wetherall */ diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordsManagementServiceImplTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordsManagementServiceImplTest.java index 610175439f..5a463ede35 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordsManagementServiceImplTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordsManagementServiceImplTest.java @@ -574,10 +574,7 @@ public class RecordsManagementServiceImplTest extends BaseRMTestCase }); } - /********** Record methods **********/ - // TODO void testGetRecordFolders(NodeRef record); - /********** RM2 - Multi-hierarchy record taxonomy's **********/ /** diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/VitalRecordServiceImplTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/VitalRecordServiceImplTest.java index ce07978310..a714452d41 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/VitalRecordServiceImplTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/VitalRecordServiceImplTest.java @@ -20,7 +20,7 @@ package org.alfresco.module.org_alfresco_module_rm.test.service; import java.util.Date; -import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementSearchBehaviour; +import org.alfresco.module.org_alfresco_module_rm.model.behaviour.RecordsManagementSearchBehaviour; import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; import org.alfresco.module.org_alfresco_module_rm.vital.VitalRecordDefinition; import org.alfresco.repo.security.authentication.AuthenticationUtil; diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/system/DOD5015SystemTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/system/DOD5015SystemTest.java deleted file mode 100644 index 5d4ab0fcfe..0000000000 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/system/DOD5015SystemTest.java +++ /dev/null @@ -1,4582 +0,0 @@ -/* - * Copyright (C) 2005-2011 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.system; - -import java.io.File; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.transaction.UserTransaction; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.model.ContentModel; -import org.alfresco.module.org_alfresco_module_rm.RecordsManagementAdminService; -import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; -import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementActionResult; -import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementActionService; -import org.alfresco.module.org_alfresco_module_rm.action.impl.BroadcastDispositionActionDefinitionUpdateAction; -import org.alfresco.module.org_alfresco_module_rm.action.impl.CompleteEventAction; -import org.alfresco.module.org_alfresco_module_rm.action.impl.EditDispositionActionAsOfDateAction; -import org.alfresco.module.org_alfresco_module_rm.action.impl.EditReviewAsOfDateAction; -import org.alfresco.module.org_alfresco_module_rm.action.impl.FileAction; -import org.alfresco.module.org_alfresco_module_rm.action.impl.FreezeAction; -import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; -import org.alfresco.module.org_alfresco_module_rm.caveat.RMCaveatConfigService; -import org.alfresco.module.org_alfresco_module_rm.caveat.RMListOfValuesConstraint.MatchLogic; -import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionAction; -import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition; -import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule; -import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService; -import org.alfresco.module.org_alfresco_module_rm.dod5015.DOD5015Model; -import org.alfresco.module.org_alfresco_module_rm.event.EventCompletionDetails; -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.model.RecordsManagementSearchBehaviour; -import org.alfresco.module.org_alfresco_module_rm.test.util.TestUtilities; -import org.alfresco.module.org_alfresco_module_rm.vital.VitalRecordDefinition; -import org.alfresco.module.org_alfresco_module_rm.vital.VitalRecordService; -import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.repo.node.integrity.IntegrityException; -import org.alfresco.repo.search.impl.lucene.AbstractLuceneQueryParser; -import org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; -import org.alfresco.repo.security.permissions.AccessDeniedException; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.dictionary.DataTypeDefinition; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.ContentReader; -import org.alfresco.service.cmr.repository.ContentService; -import org.alfresco.service.cmr.repository.ContentWriter; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.Period; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.search.ResultSet; -import org.alfresco.service.cmr.search.SearchService; -import org.alfresco.service.cmr.security.AccessStatus; -import org.alfresco.service.cmr.security.AuthorityService; -import org.alfresco.service.cmr.security.AuthorityType; -import org.alfresco.service.cmr.security.MutableAuthenticationService; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.cmr.security.PersonService; -import org.alfresco.service.cmr.security.PublicServiceAccessService; -import org.alfresco.service.cmr.site.SiteVisibility; -import org.alfresco.service.cmr.view.ImporterService; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.namespace.RegexQNamePattern; -import org.alfresco.service.transaction.TransactionService; -import org.alfresco.util.BaseSpringTest; -import org.alfresco.util.GUID; -import org.alfresco.util.PropertyMap; - -/** - * DOD System Test - * - * @author Roy Wetherall, Neil McErlean - */ -public class DOD5015SystemTest extends BaseSpringTest implements RecordsManagementModel, DOD5015Model -{ - private static final Period weeklyReview = new Period("week|1"); - private static final Period dailyReview = new Period("day|1"); - public static final long TWENTY_FOUR_HOURS_IN_MS = 24 * 60 * 60 * 1000; // hours * minutes * seconds * millis - - protected static StoreRef SPACES_STORE = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore"); - - private NodeRef filePlan; - - private NodeService unprotectedNodeService; - private NodeService nodeService; - private SearchService searchService; - private ImporterService importService; - private ContentService contentService; - private RecordsManagementService rmService; - private RecordsManagementActionService rmActionService; - private ServiceRegistry serviceRegistry; - private TransactionService transactionService; - private RecordsManagementAdminService rmAdminService; - private RMCaveatConfigService caveatConfigService; - private DispositionService dispositionService; - private VitalRecordService vitalRecordService; - - private MutableAuthenticationService authenticationService; - private PersonService personService; - private AuthorityService authorityService; - private PermissionService permissionService; - private RetryingTransactionHelper transactionHelper; - - private PublicServiceAccessService publicServiceAccessService; - private FullTextSearchIndexer luceneFTS; - - // example base test data for supplemental markings list (see also recordsModel.xml) - protected final static String NOFORN = "NOFORN"; // Not Releasable to Foreign Nationals/Governments/Non-US Citizens - protected final static String NOCONTRACT = "NOCONTRACT"; // Not Releasable to Contractors or Contractor/Consultants - protected final static String FOUO = "FOUO"; // For Official Use Only - protected final static String FGI = "FGI"; // Foreign Government Information - - // example user-defined field - protected final static QName CONSTRAINT_CUSTOM_PRJLIST = QName.createQName(RM_CUSTOM_URI, "prjList"); - protected final static QName PROP_CUSTOM_PRJLIST = QName.createQName(RM_CUSTOM_URI, "projectNameList"); - - protected final static String PRJ_A = "Project A"; - protected final static String PRJ_B = "Project B"; - protected final static String PRJ_C = "Project C"; - - @Override - protected void onSetUpInTransaction() throws Exception - { - super.onSetUpInTransaction(); - - // Get the service required in the tests - this.unprotectedNodeService = (NodeService)applicationContext.getBean("nodeService"); - this.nodeService = (NodeService)this.applicationContext.getBean("NodeService"); // use upper 'N'odeService (to test access config interceptor) NodeService unprotectedNodeService = (NodeService)applicationContext.getBean("nodeService"); - this.authenticationService = (MutableAuthenticationService)this.applicationContext.getBean("AuthenticationService"); - this.personService = (PersonService)this.applicationContext.getBean("PersonService"); - this.authorityService = (AuthorityService)this.applicationContext.getBean("AuthorityService"); - this.permissionService = (PermissionService)this.applicationContext.getBean("PermissionService"); - this.searchService = (SearchService)this.applicationContext.getBean("SearchService"); // use upper 'S'earchService (to test access config interceptor) - this.importService = (ImporterService)this.applicationContext.getBean("importerComponent"); - this.contentService = (ContentService)this.applicationContext.getBean("ContentService"); - this.rmService = (RecordsManagementService)this.applicationContext.getBean("RecordsManagementService"); - this.rmActionService = (RecordsManagementActionService)this.applicationContext.getBean("RecordsManagementActionService"); - this.serviceRegistry = (ServiceRegistry)this.applicationContext.getBean("ServiceRegistry"); - this.transactionService = (TransactionService)this.applicationContext.getBean("TransactionService"); - this.rmAdminService = (RecordsManagementAdminService)this.applicationContext.getBean("RecordsManagementAdminService"); - this.caveatConfigService = (RMCaveatConfigService)this.applicationContext.getBean("caveatConfigService"); - this.publicServiceAccessService = (PublicServiceAccessService)this.applicationContext.getBean("PublicServiceAccessService"); - this.transactionHelper = (RetryingTransactionHelper)this.applicationContext.getBean("retryingTransactionHelper"); - this.dispositionService = (DispositionService)this.applicationContext.getBean("DispositionService"); - this.luceneFTS = (FullTextSearchIndexer)this.applicationContext.getBean("LuceneFullTextSearchIndexer"); - this.vitalRecordService = (VitalRecordService)applicationContext.getBean("VitalRecordService"); - - - // Set the current security context as admin - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); - - // Get the test data - filePlan = TestUtilities.loadFilePlanData(applicationContext); - - File file = new File(System.getProperty("user.dir")+"/test-resources/testCaveatConfig1.json"); // from test-resources - assertTrue(file.exists()); - - caveatConfigService.updateOrCreateCaveatConfig(file); - - // set/reset allowed values (empty list by default) - List newValues = new ArrayList(4); - newValues.add(NOFORN); - newValues.add(NOCONTRACT); - newValues.add(FOUO); - newValues.add(FGI); - - rmAdminService.changeCustomConstraintValues(RecordsManagementCustomModel.CONSTRAINT_CUSTOM_SMLIST, newValues); - - // We pause FTS during this test, as it moves around records in intermediate places, and otherwise FTS may not - // finish clearing up its mess before each test finishes - this.luceneFTS.pause(); - } - - - - /* (non-Javadoc) - * @see org.springframework.test.AbstractTransactionalSpringContextTests#onTearDown() - */ - @Override - protected void onTearDown() throws Exception - { - super.onTearDown(); - - // Let FTS catch up again. - this.luceneFTS.resume(); - } - - - - /** - * Tests that the test data has been loaded correctly - */ - public void xtestTestData() throws Exception - { - // make sure the folders that should have disposition schedules do so - NodeRef janAuditRecordsFolder = TestUtilities.getRecordFolder(rmService, nodeService, "Reports", "AIS Audit Records", "January AIS Audit Records"); - assertNotNull(janAuditRecordsFolder); - - // ensure the folder has the disposition lifecycle aspect - assertTrue("Expected 'January AIS Audit Records' folder to have disposition lifecycle aspect applied", - nodeService.hasAspect(janAuditRecordsFolder, ASPECT_DISPOSITION_LIFECYCLE)); - - // ensure the folder has the correctly setup search aspect - checkSearchAspect(janAuditRecordsFolder); - - // check another folder that has events as part of the disposition schedule - NodeRef equalOppCoordFolder = TestUtilities.getRecordFolder(rmService, nodeService, "Military Files", "Personnel Security Program Records", "Equal Opportunity Coordinator"); - assertNotNull(equalOppCoordFolder); - assertTrue("Expected 'Equal Opportunity Coordinator' folder to have disposition lifecycle aspect applied", - nodeService.hasAspect(equalOppCoordFolder, ASPECT_DISPOSITION_LIFECYCLE)); - checkSearchAspect(equalOppCoordFolder); - } - - /** - * This test method creates a non-vital record and then moves it to a vital folder - * (triggering a refile) and then moves it a second time to another vital record - * having different metadata. - * - * Moving a Record within the FilePlan should trigger a "refile". Refiling a record - * will lead to the reconsideration of its disposition, vital and transfer/accession - * metadata, with potential changes therein. - */ - public void testMoveRefileRecord() throws Exception - { - // Commit in order to trigger the setUpRecordFolder behaviour - setComplete(); - endTransaction(); - - final NodeRef nonVitalFolder = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - // Create a record folder under a "non-vital" category - NodeRef nonVitalRecordCategory = TestUtilities.getRecordCategory(rmService, nodeService, "Reports", "Unit Manning Documents"); - assertNotNull(nonVitalRecordCategory); - - return createRecFolderNode(nonVitalRecordCategory); - } - }); - - final NodeRef recordUnderTest = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - // Create a (non-vital) record under the above folder - NodeRef recordUnderTest = createRecordNode(nonVitalFolder); - - rmActionService.executeRecordsManagementAction(recordUnderTest, "file"); - - TestUtilities.declareRecord(recordUnderTest, unprotectedNodeService, rmActionService); - - return recordUnderTest; - } - }); - - final NodeRef vitalFolder =transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - // No need to commit the transaction here as the record is non-vital and - // there is no metadata to copy down. - - NodeRef vitalFolder = retrieveJanuaryAISVitalFolder(); - - // Move the non-vital record under the vital folder. - serviceRegistry.getFileFolderService().move(recordUnderTest, vitalFolder, null); - - return vitalFolder; - } - }); - - final NodeRef secondVitalFolder = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - // At this point, the formerly nonVitalRecord is now actually vital. - assertTrue("Expected record.", rmService.isRecord(recordUnderTest)); - assertTrue("Expected declared.", rmService.isRecordDeclared(recordUnderTest)); - - final VitalRecordDefinition recordVrd = vitalRecordService.getVitalRecordDefinition(recordUnderTest); - assertNotNull("Moved record should now have a Vital Rec Defn", recordVrd); - assertEquals("Moved record had wrong review period", - vitalRecordService.getVitalRecordDefinition(vitalFolder).getReviewPeriod(), recordVrd.getReviewPeriod()); - assertNotNull("Moved record should now have a review-as-of date", nodeService.getProperty(recordUnderTest, PROP_REVIEW_AS_OF)); - - // Create another folder with different vital/disposition instructions - //TODO Change disposition instructions - NodeRef vitalRecordCategory = TestUtilities.getRecordCategory(rmService, nodeService, "Reports", "AIS Audit Records"); - assertNotNull(vitalRecordCategory); - return createRecFolderNode(vitalRecordCategory); - } - }); - - final Date reviewDate = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Date execute() throws Throwable - { - Map props = nodeService.getProperties(secondVitalFolder); - final Serializable secondVitalFolderReviewPeriod = props.get(PROP_REVIEW_PERIOD); - assertEquals("Unexpected review period.", weeklyReview, secondVitalFolderReviewPeriod); - - // We are changing the review period of this second record folder. - nodeService.setProperty(secondVitalFolder, PROP_REVIEW_PERIOD, dailyReview); - - Date reviewDate = (Date)nodeService.getProperty(recordUnderTest, PROP_REVIEW_AS_OF); - - // Move the newly vital record under the second vital folder. I expect the reviewPeriod - // for the record to be changed again. - serviceRegistry.getFileFolderService().move(recordUnderTest, secondVitalFolder, null); - - return reviewDate; - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - Period newReviewPeriod = vitalRecordService.getVitalRecordDefinition(recordUnderTest).getReviewPeriod(); - assertEquals("Unexpected review period.", dailyReview, newReviewPeriod); - - Date updatedReviewDate = (Date)nodeService.getProperty(recordUnderTest, PROP_REVIEW_AS_OF); - // The reviewAsOf date should have changed to "24 hours from now". - assertFalse("reviewAsOf date was unchanged", reviewDate.equals(updatedReviewDate)); - long millisecondsUntilNextReview = updatedReviewDate.getTime() - new Date().getTime(); - assertTrue("new reviewAsOf date was not within 24 hours of now.", - millisecondsUntilNextReview <= TWENTY_FOUR_HOURS_IN_MS); - - nodeService.deleteNode(recordUnderTest); - nodeService.deleteNode(nonVitalFolder); - nodeService.deleteNode(secondVitalFolder); - - return null; - } - }); - } - - public void off_testMoveRefileRecordFolder() throws Exception - { - //TODO Impl me - fail("Not yet impl'd."); - } - - public void off_testCopyRefileRecordFolder() throws Exception - { - //TODO Impl me - fail("Not yet impl'd."); - } - - public void off_testCopyRefileRecord() throws Exception - { - //TODO Impl me - fail("Not yet impl'd."); - } - - private NodeRef createRecordCategoryNode(NodeRef parentRecordSeries) - { - NodeRef newCategory = this.nodeService.createNode(parentRecordSeries, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "Test category " + System.currentTimeMillis()), - TYPE_RECORD_CATEGORY).getChildRef(); - - return newCategory; - } - - private NodeRef createRecFolderNode(NodeRef parentRecordCategory) - { - NodeRef newFolder = this.nodeService.createNode(parentRecordCategory, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "Test folder " + System.currentTimeMillis()), - TYPE_RECORD_FOLDER).getChildRef(); - return newFolder; - } - - private NodeRef createRecordNode(NodeRef parentFolder) - { - NodeRef newRecord = this.nodeService.createNode(parentFolder, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, - "Record" + System.currentTimeMillis() + ".txt"), - ContentModel.TYPE_CONTENT).getChildRef(); - ContentWriter writer = this.contentService.getWriter(newRecord, ContentModel.PROP_CONTENT, true); - writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); - writer.setEncoding("UTF-8"); - writer.putContent("Irrelevant content"); - return newRecord; - } - - private NodeRef retrieveJanuaryAISVitalFolder() - { - final List resultNodeRefs = retrieveJanuaryAISVitalFolders(); - final int folderCount = resultNodeRefs.size(); -// assertTrue("There should only be one 'January AIS Audit Records' folder. Were " + folderCount, folderCount == 1); - - // This nodeRef should have rma:VRI=true, rma:reviewPeriod=week|1, rma:isClosed=false - return resultNodeRefs.get(0); - } - - private List retrieveJanuaryAISVitalFolders() - { - String typeQuery = "TYPE:\"" + TYPE_RECORD_FOLDER + "\" AND @cm\\:name:\"January AIS Audit Records\""; - ResultSet types = this.searchService.query(SPACES_STORE, SearchService.LANGUAGE_LUCENE, typeQuery); - - final List resultNodeRefs = types.getNodeRefs(); - types.close(); - return resultNodeRefs; - } - - /** - * Test duplicate id's - */ - public void xxtestDuplicateIDs() - { - List roots = rmService.getFilePlans(); - final NodeRef root = roots.get(0); - setComplete(); - endTransaction(); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - String name1 = GUID.generate(); - Map props = new HashMap(2); - props.put(ContentModel.PROP_NAME, name1); - props.put(PROP_IDENTIFIER, "bob"); - ChildAssociationRef assoc = nodeService.createNode( - root, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, name1), - TYPE_RECORD_CATEGORY, - props); - - return assoc.getChildRef(); - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - try - { - String name1 = GUID.generate(); - Map props = new HashMap(2); - props.put(ContentModel.PROP_NAME, name1); - props.put(PROP_IDENTIFIER, "bob"); - ChildAssociationRef assoc = nodeService.createNode( - root, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, name1), - TYPE_RECORD_CATEGORY, - props); - fail("Cant duplicate series id"); - } - catch (Exception e) - { - // expected - } - - return null; - } - }); - } - - public void testDispositionLifecycle_0318_01_basictest() throws Exception - { - final NodeRef recordCategory = TestUtilities.getRecordCategory(rmService, nodeService, "Reports", "AIS Audit Records"); - setComplete(); - endTransaction(); - - final NodeRef recordFolder = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - - assertNotNull(recordCategory); - assertEquals("AIS Audit Records", nodeService.getProperty(recordCategory, ContentModel.PROP_NAME)); - - return createRecordFolder(recordCategory, "March AIS Audit Records"); - } - }); - - final NodeRef recordOne = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - // Check the folder to ensure everything has been inherited correctly - assertTrue(((Boolean)nodeService.getProperty(recordFolder, PROP_VITAL_RECORD_INDICATOR)).booleanValue()); - assertEquals(nodeService.getProperty(recordCategory, PROP_REVIEW_PERIOD), - nodeService.getProperty(recordFolder, PROP_REVIEW_PERIOD)); - - // Create the document - Map props = new HashMap(1); - props.put(ContentModel.PROP_NAME, "MyRecord.txt"); - NodeRef recordOne = nodeService.createNode(recordFolder, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "MyRecord.txt"), - ContentModel.TYPE_CONTENT).getChildRef(); - - // Set the content - ContentWriter writer = contentService.getWriter(recordOne, ContentModel.PROP_CONTENT, true); - writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); - writer.setEncoding("UTF-8"); - writer.putContent("There is some content in this record"); - - return recordOne; - } - }); - - // Checked that the document has been marked as incomplete - System.out.println("recordOne ..."); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - assertTrue(nodeService.hasAspect(recordOne, ASPECT_RECORD)); - assertNotNull(nodeService.getProperty(recordOne, PROP_IDENTIFIER)); - System.out.println("Record id: " + nodeService.getProperty(recordOne, PROP_IDENTIFIER)); - assertNotNull(nodeService.getProperty(recordOne, PROP_DATE_FILED)); - System.out.println("Date filed: " + nodeService.getProperty(recordOne, PROP_DATE_FILED)); - - // Check the review schedule - assertTrue(nodeService.hasAspect(recordOne, ASPECT_VITAL_RECORD)); - assertNotNull(nodeService.getProperty(recordOne, PROP_REVIEW_AS_OF)); - System.out.println("Review as of: " + nodeService.getProperty(recordOne, PROP_REVIEW_AS_OF)); - - // Change the review asOf date - Date nowDate = new Date(); - assertFalse(nowDate.equals(nodeService.getProperty(recordOne, PROP_REVIEW_AS_OF))); - Map reviewAsOfParams = new HashMap(1); - reviewAsOfParams.put(EditReviewAsOfDateAction.PARAM_AS_OF_DATE, nowDate); - rmActionService.executeRecordsManagementAction(recordOne, "editReviewAsOfDate", reviewAsOfParams); - assertTrue(nowDate.equals(nodeService.getProperty(recordOne, PROP_REVIEW_AS_OF))); - - // NOTE the disposition is being managed at a folder level ... - - // Check the disposition action - assertFalse(nodeService.hasAspect(recordOne, ASPECT_DISPOSITION_LIFECYCLE)); - assertTrue(nodeService.hasAspect(recordFolder, ASPECT_DISPOSITION_LIFECYCLE)); - - NodeRef ndNodeRef = nodeService.getChildAssocs(recordFolder, ASSOC_NEXT_DISPOSITION_ACTION, RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(ndNodeRef); - - assertNotNull(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION_ID)); - System.out.println("Disposition action id: " + nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION_ID)); - assertEquals("cutoff", nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION)); - System.out.println("Disposition action: " + nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION)); - assertNotNull(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF)); - System.out.println("Disposition as of: " + nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF)); - - // Check for the search properties having been populated - checkSearchAspect(recordFolder); - - // Test the declaration of a record by editing properties - Map propValues = new HashMap(); - propValues.put(RecordsManagementModel.PROP_PUBLICATION_DATE, new Date()); - List smList = new ArrayList(2); - smList.add(FOUO); - smList.add(NOFORN); - propValues.put(RecordsManagementModel.PROP_SUPPLEMENTAL_MARKING_LIST, (Serializable)smList); - propValues.put(RecordsManagementModel.PROP_MEDIA_TYPE, "mediaTypeValue"); - propValues.put(RecordsManagementModel.PROP_FORMAT, "formatValue"); - propValues.put(RecordsManagementModel.PROP_DATE_RECEIVED, new Date()); - nodeService.addProperties(recordOne, propValues); - - return null; - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // Try and declare, expected failure - try - { - rmActionService.executeRecordsManagementAction(recordOne, "declareRecord"); - fail("Should not be able to declare a record that still has mandatory properties unset"); - } - catch (Exception e) - { - // Expected - } - - return null; - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("deprecation") - public Object execute() throws Throwable - { - assertTrue("Before test DECLARED aspect was set", - nodeService.hasAspect(recordOne, ASPECT_DECLARED_RECORD) == false); - - nodeService.setProperty(recordOne, RecordsManagementModel.PROP_ORIGINATOR, "origValue"); - nodeService.setProperty(recordOne, RecordsManagementModel.PROP_ORIGINATING_ORGANIZATION, "origOrgValue"); - nodeService.setProperty(recordOne, ContentModel.PROP_TITLE, "titleValue"); - - // Declare the record as we have set everything we should have - rmActionService.executeRecordsManagementAction(recordOne, "declareRecord"); - assertTrue(" the record is not declared", nodeService.hasAspect(recordOne, ASPECT_DECLARED_RECORD)); - - // check that the declaredAt and declaredBy properties are set - assertNotNull(nodeService.getProperty(recordOne, PROP_DECLARED_BY)); - assertEquals("admin", nodeService.getProperty(recordOne, PROP_DECLARED_BY)); - assertNotNull(nodeService.getProperty(recordOne, PROP_DECLARED_AT)); - Date dateNow = new Date(); - Date declaredDate = (Date)nodeService.getProperty(recordOne, PROP_DECLARED_AT); - assertEquals(declaredDate.getDate(), dateNow.getDate()); - assertEquals(declaredDate.getMonth(), dateNow.getMonth()); - assertEquals(declaredDate.getYear(), dateNow.getYear()); - - // Check that the history is empty - List history = dispositionService.getCompletedDispositionActions(recordFolder); - assertNotNull(history); - assertEquals(0, history.size()); - - return null; - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // Execute the cutoff action (should fail because this is being done at the record level) - try - { - rmActionService.executeRecordsManagementAction(recordFolder, "cutoff", null); - fail(("Shouldn't have been able to execute cut off at the record level")); - } - catch (Exception e) - { - // expected - } - - // Execute the cutoff action (should fail becuase it is not yet eligiable) - try - { - rmActionService.executeRecordsManagementAction(recordFolder, "cutoff", null); - fail(("Shouldn't have been able to execute because it is not yet eligiable")); - } - catch (Exception e) - { - // expected - } - - return null; - } - }); - - final Calendar calendar = Calendar.getInstance(); - calendar.set(Calendar.HOUR, 0); - calendar.set(Calendar.MINUTE, 0); - calendar.set(Calendar.SECOND, 0); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // Clock the asOf date back to ensure eligibility - NodeRef ndNodeRef = nodeService.getChildAssocs(recordFolder, ASSOC_NEXT_DISPOSITION_ACTION, RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - Date nowDate = calendar.getTime(); - assertFalse(nowDate.equals(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF))); - Map params = new HashMap(1); - params.put(EditDispositionActionAsOfDateAction.PARAM_AS_OF_DATE, nowDate); - rmActionService.executeRecordsManagementAction(recordFolder, "editDispositionActionAsOfDate", params); - assertTrue(nowDate.equals(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF))); - - // Cut off - rmActionService.executeRecordsManagementAction(recordFolder, "cutoff", null); - - return null; - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // Check the disposition action - assertFalse(nodeService.hasAspect(recordOne, ASPECT_DISPOSITION_LIFECYCLE)); - assertTrue(nodeService.hasAspect(recordFolder, ASPECT_DISPOSITION_LIFECYCLE)); - - NodeRef ndNodeRef = nodeService.getChildAssocs(recordFolder, ASSOC_NEXT_DISPOSITION_ACTION, RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(ndNodeRef); - - assertNotNull(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION_ID)); - System.out.println("Disposition action id: " + nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION_ID)); - assertEquals("destroy", nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION)); - System.out.println("Disposition action: " + nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION)); - assertNotNull(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF)); - System.out.println("Disposition as of: " + nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF)); - assertNull(nodeService.getProperty(recordFolder, RecordsManagementSearchBehaviour.PROP_RS_DISPOSITION_EVENTS)); - - // Check the previous action details - checkLastDispositionAction(recordFolder, "cutoff", 1); - - // Check for the search properties having been populated - checkSearchAspect(recordFolder); - - // Clock the asOf date back to ensure eligibility - ndNodeRef = nodeService.getChildAssocs(recordFolder, ASSOC_NEXT_DISPOSITION_ACTION, RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - Date nowDate = calendar.getTime(); - assertFalse(nowDate.equals(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF))); - Map params = new HashMap(1); - params.put(EditDispositionActionAsOfDateAction.PARAM_AS_OF_DATE, nowDate); - rmActionService.executeRecordsManagementAction(recordFolder, "editDispositionActionAsOfDate", params); - assertTrue(nowDate.equals(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF))); - - rmActionService.executeRecordsManagementAction(recordFolder, "destroy", null); - - // Check that the node has been destroyed (ghosted) - //assertFalse(nodeService.exists(recordFolder)); - //assertFalse(nodeService.exists(recordOne)); - assertTrue(nodeService.hasAspect(recordFolder, ASPECT_GHOSTED)); - assertTrue(nodeService.hasAspect(recordOne, ASPECT_GHOSTED)); - - // Check the history - if (nodeService.exists(recordFolder) == true) - { - checkLastDispositionAction(recordFolder, "destroy", 2); - } - - return null; - } - }); - } - - /** - * Tests the re-scheduling of disposition lifecycles when the schedule changes - */ - public void testDispositionLifecycle_0318_reschedule_folderlevel() throws Exception - { - final NodeRef recordSeries = TestUtilities.getRecordSeries(rmService, nodeService, "Reports"); - setComplete(); - endTransaction(); - - // create a category - final NodeRef recordCategory = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - assertNotNull(recordSeries); - assertEquals("Reports", nodeService.getProperty(recordSeries, ContentModel.PROP_NAME)); - - return createRecordCategoryNode(recordSeries); - } - }); - - // define the disposition schedule for the category (Cut off monthly, hold 1 month, then destroy) - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - assertNotNull(recordCategory); - - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - nodeService.setProperty(schedule.getNodeRef(), PROP_DISPOSITION_INSTRUCTIONS, "Cutoff after 1 month then destroy after 1 month"); - nodeService.setProperty(schedule.getNodeRef(), PROP_DISPOSITION_AUTHORITY, "Alfresco"); - - // define properties for both steps - Map step1 = new HashMap(); - step1.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_NAME, "cutoff"); - step1.put(RecordsManagementModel.PROP_DISPOSITION_DESCRIPTION, "Cutoff after 1 month"); - step1.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, "month|1"); - - Map step2 = new HashMap(); - step2.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_NAME, "destroy"); - step2.put(RecordsManagementModel.PROP_DISPOSITION_DESCRIPTION, "Destroy after 1 month"); - step2.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, "month|1"); - step2.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD_PROPERTY, PROP_CUT_OFF_DATE); - - // add the action definitions to the schedule - dispositionService.addDispositionActionDefinition(schedule, step1); - dispositionService.addDispositionActionDefinition(schedule, step2); - - return null; - } - }); - - // create a record folder - final NodeRef recordFolder = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - return createRecordFolder(recordCategory, "Folder1"); - } - }); - - // make sure the disposition lifecycle is present and correct - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("deprecation") - public Object execute() throws Throwable - { - assertNotNull(recordFolder); - - assertTrue(nodeService.hasAspect(recordFolder, ASPECT_DISPOSITION_LIFECYCLE)); - NodeRef ndNodeRef = nodeService.getChildAssocs(recordFolder, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(ndNodeRef); - - assertNotNull(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION_ID)); - System.out.println("Disposition action id: " + nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION_ID)); - assertEquals("cutoff", nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION)); - System.out.println("Disposition action: " + nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION)); - assertNotNull(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF)); - Date asOfDate = (Date)nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF); - System.out.println("Disposition as of: " + asOfDate); - - // make sure the as of date is a month in the future - Calendar cal = Calendar.getInstance(); - cal.add(Calendar.MONTH, 1); - int monthThen = cal.get(Calendar.MONTH); - assertEquals(asOfDate.getMonth(), monthThen);; - - // make sure there aren't any events - List events = nodeService.getChildAssocs(ndNodeRef, ASSOC_EVENT_EXECUTIONS, - RegexQNamePattern.MATCH_ALL); - assertEquals(0, events.size()); - - // Check for the search properties having been populated - checkSearchAspect(recordFolder); - - return null; - } - }); - - // change the period on the 1st step of the disposition schedule and make sure it perculates down - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // define changes for schedule - Map changes = new HashMap(); - changes.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, "month|3"); - - // update the second dispostion action definition - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - List actionDefs = schedule.getDispositionActionDefinitions(); - assertEquals(2, actionDefs.size()); - System.out.println("Adding 3 months to period for 1st step: " + actionDefs.get(0).getName()); - updateDispositionActionDefinition(schedule, actionDefs.get(0), changes); - - return null; - } - }); - - // make sure the disposition lifecycle asOf date has been updated - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("deprecation") - public Object execute() throws Throwable - { - assertTrue(nodeService.hasAspect(recordFolder, ASPECT_DISPOSITION_LIFECYCLE)); - NodeRef ndNodeRef = nodeService.getChildAssocs(recordFolder, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(ndNodeRef); - - assertNotNull(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF)); - Date asOfDate = (Date)nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF); - System.out.println("Disposition as of: " + asOfDate); - - // make sure the as of date is a month in the future - Calendar calendar = Calendar.getInstance(); - calendar.add(Calendar.MONTH, 3); - System.out.println("Test date: " + calendar.getTime()); - Calendar asOfCalendar = Calendar.getInstance(); - asOfCalendar.setTime(asOfDate); - assertEquals(calendar.get(Calendar.MONTH), asOfCalendar.get(Calendar.MONTH)); - - // Check for the search properties having been populated - checkSearchAspect(recordFolder); - - return null; - } - }); - - // change the period on the 2nd step of the disposition schedule and make sure it DOES NOT perculate down - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // define changes for schedule - Map changes = new HashMap(); - changes.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, "month|6"); - - // update the first dispostion action definition - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - List actionDefs = schedule.getDispositionActionDefinitions(); - assertEquals(2, actionDefs.size()); - System.out.println("Adding 6 months to period for 2nd step: " + actionDefs.get(1).getName()); - updateDispositionActionDefinition(schedule, actionDefs.get(1), changes); - - return null; - } - }); - - // make sure the disposition lifecycle asOf date has NOT been updated as the period was - // changed for a step other than the current one - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("deprecation") - public Object execute() throws Throwable - { - assertTrue(nodeService.hasAspect(recordFolder, ASPECT_DISPOSITION_LIFECYCLE)); - NodeRef ndNodeRef = nodeService.getChildAssocs(recordFolder, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(ndNodeRef); - - assertNotNull(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF)); - Date asOfDate = (Date)nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF); - System.out.println("Disposition as of: " + asOfDate); - - // make sure the as of date is a month in the future - Calendar calendar = Calendar.getInstance(); - calendar.add(Calendar.MONTH, 3); - assertEquals("Expecting the asOf date to be unchanged",asOfDate.getMonth(), calendar.get(Calendar.MONTH)); - - // Check for the search properties having been populated - checkSearchAspect(recordFolder); - - return null; - } - }); - - // change the disposition schedule to be event based rather than time based i.e. - // remove the period properties and supply 2 events in its place. - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // define changes for schedule - Map changes = new HashMap(); - changes.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, null); - List events = new ArrayList(2); - events.add("no_longer_needed"); - events.add("case_complete"); - changes.put(RecordsManagementModel.PROP_DISPOSITION_EVENT, (Serializable)events); - - // update the first dispostion action definition - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - List actionDefs = schedule.getDispositionActionDefinitions(); - assertEquals(2, actionDefs.size()); - System.out.println("Removing period and adding no_longer_needed and case_complete to 1st step: " + - actionDefs.get(0).getName()); - updateDispositionActionDefinition(schedule, actionDefs.get(0), changes); - - return null; - } - }); - - // make sure the disposition lifecycle asOf date has been reset and there are now - // events hanging off the nextdispositionaction node - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - assertTrue(nodeService.hasAspect(recordFolder, ASPECT_DISPOSITION_LIFECYCLE)); - NodeRef ndNodeRef = nodeService.getChildAssocs(recordFolder, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(ndNodeRef); - - Date asOfDate = (Date)nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF); - System.out.println("New disposition as of: " + asOfDate); - assertNull("Expecting asOfDate to be null", asOfDate); - - // make sure the 2 events are present - List events = nodeService.getChildAssocs(ndNodeRef, ASSOC_EVENT_EXECUTIONS, - RegexQNamePattern.MATCH_ALL); - assertEquals(2, events.size()); - NodeRef event1 = events.get(0).getChildRef(); - assertEquals("no_longer_needed", nodeService.getProperty(event1, PROP_EVENT_EXECUTION_NAME)); - NodeRef event2 = events.get(1).getChildRef(); - assertEquals("case_complete", nodeService.getProperty(event2, PROP_EVENT_EXECUTION_NAME)); - - // Check for the search properties having been populated - checkSearchAspect(recordFolder, false); - - return null; - } - }); - - // remove one of the events just added - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // define changes for schedule - Map changes = new HashMap(); - List events = new ArrayList(2); - events.add("case_complete"); - changes.put(RecordsManagementModel.PROP_DISPOSITION_EVENT, (Serializable)events); - - // update the first dispostion action definition - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - List actionDefs = schedule.getDispositionActionDefinitions(); - assertEquals(2, actionDefs.size()); - System.out.println("Removing no_longer_needed event from 1st step: " + - actionDefs.get(0).getName()); - updateDispositionActionDefinition(schedule, actionDefs.get(0), changes); - - return null; - } - }); - - // make sure the disposition lifecycle asOf date is still null and ensure there is only one event - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - assertTrue(nodeService.hasAspect(recordFolder, ASPECT_DISPOSITION_LIFECYCLE)); - NodeRef ndNodeRef = nodeService.getChildAssocs(recordFolder, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(ndNodeRef); - - Date asOfDate = (Date)nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF); - assertNull("Expecting asOfDate to be null", asOfDate); - - // make sure only 1 event is present - List events = nodeService.getChildAssocs(ndNodeRef, ASSOC_EVENT_EXECUTIONS, - RegexQNamePattern.MATCH_ALL); - assertEquals(1, events.size()); - NodeRef event = events.get(0).getChildRef(); - assertEquals("case_complete", nodeService.getProperty(event, PROP_EVENT_EXECUTION_NAME)); - - // Check for the search properties having been populated - checkSearchAspect(recordFolder, false); - - return null; - } - }); - } - - /** - * Tests the re-scheduling of disposition lifecycles when the schedule changes - */ - public void testDispositionLifecycle_0318_reschedule_recordlevel() throws Exception - { - final NodeRef recordSeries = TestUtilities.getRecordSeries(rmService, nodeService, "Reports"); - setComplete(); - endTransaction(); - - // create a category - final NodeRef recordCategory = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - assertNotNull(recordSeries); - assertEquals("Reports", nodeService.getProperty(recordSeries, ContentModel.PROP_NAME)); - - return createRecordCategoryNode(recordSeries); - } - }); - - // define the disposition schedule for the category (Cut off monthly, hold 1 month, then destroy) - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - assertNotNull(recordCategory); - - // get the disposition schedule and turn on record level disposition - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - nodeService.setProperty(schedule.getNodeRef(), PROP_DISPOSITION_INSTRUCTIONS, "Cutoff after 1 month then destroy after 1 month"); - nodeService.setProperty(schedule.getNodeRef(), PROP_DISPOSITION_AUTHORITY, "Alfresco"); - nodeService.setProperty(schedule.getNodeRef(), PROP_RECORD_LEVEL_DISPOSITION, true); - - // define properties for both steps - Map step1 = new HashMap(); - step1.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_NAME, "cutoff"); - step1.put(RecordsManagementModel.PROP_DISPOSITION_DESCRIPTION, "Cutoff after 1 month"); - step1.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, "month|1"); - - Map step2 = new HashMap(); - step2.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_NAME, "destroy"); - step2.put(RecordsManagementModel.PROP_DISPOSITION_DESCRIPTION, "Destroy after 1 month"); - step2.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, "month|1"); - step2.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD_PROPERTY, PROP_CUT_OFF_DATE); - - // add the action definitions to the schedule - dispositionService.addDispositionActionDefinition(schedule, step1); - dispositionService.addDispositionActionDefinition(schedule, step2); - - return null; - } - }); - - // create a record folder - final NodeRef recordFolder = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - return createRecordFolder(recordCategory, "Folder1"); - } - }); - - // create a record - final NodeRef record = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - assertNotNull(recordFolder); - - // Create the document - Map props = new HashMap(1); - props.put(ContentModel.PROP_NAME, "MyRecord.txt"); - NodeRef record = nodeService.createNode(recordFolder, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "MyRecord.txt"), - ContentModel.TYPE_CONTENT).getChildRef(); - - // Set the content - ContentWriter writer = contentService.getWriter(record, ContentModel.PROP_CONTENT, true); - writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); - writer.setEncoding("UTF-8"); - writer.putContent("There is some content in this record"); - - return record; - } - }); - - // make sure the disposition lifecycle is present and correct on the record and not on the folder - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("deprecation") - public Object execute() throws Throwable - { - assertNotNull(record); - - assertFalse(nodeService.hasAspect(recordFolder, ASPECT_DISPOSITION_LIFECYCLE)); - assertTrue(nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE)); - NodeRef ndNodeRef = nodeService.getChildAssocs(record, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(ndNodeRef); - - assertNotNull(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION_ID)); - System.out.println("Disposition action id: " + nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION_ID)); - assertEquals("cutoff", nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION)); - System.out.println("Disposition action: " + nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION)); - assertNotNull(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF)); - Date asOfDate = (Date)nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF); - System.out.println("Disposition as of: " + asOfDate); - - // make sure the as of date is a month in the future - Calendar cal = Calendar.getInstance(); - cal.add(Calendar.MONTH, 1); - int monthThen = cal.get(Calendar.MONTH); - assertEquals(asOfDate.getMonth(), monthThen); - - // make sure there aren't any events - List events = nodeService.getChildAssocs(ndNodeRef, ASSOC_EVENT_EXECUTIONS, - RegexQNamePattern.MATCH_ALL); - assertEquals(0, events.size()); - - // Check for the search properties having been populated - checkSearchAspect(record); - - return null; - } - }); - - // change the period on the 1st step of the disposition schedule and make sure it perculates down - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // define changes for schedule - Map changes = new HashMap(); - changes.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, "month|3"); - - // update the second dispostion action definition - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - List actionDefs = schedule.getDispositionActionDefinitions(); - assertEquals(2, actionDefs.size()); - System.out.println("Adding 3 months to period for 1st step: " + actionDefs.get(0).getName()); - updateDispositionActionDefinition(schedule, actionDefs.get(0), changes); - - return null; - } - }); - - // make sure the disposition lifecycle asOf date has been updated - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("deprecation") - public Object execute() throws Throwable - { - assertTrue(nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE)); - NodeRef ndNodeRef = nodeService.getChildAssocs(record, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(ndNodeRef); - - assertNotNull(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF)); - Date asOfDate = (Date)nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF); - System.out.println("Disposition as of: " + asOfDate); - - // make sure the as of date is a month in the future - Calendar calendar = Calendar.getInstance(); - calendar.add(Calendar.MONTH, 3); - assertEquals(asOfDate.getMonth(), calendar.get(Calendar.MONTH)); - - // Check for the search properties having been populated - checkSearchAspect(record); - - return null; - } - }); - - // change the period on the 2nd step of the disposition schedule and make sure it DOES NOT perculate down - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // define changes for schedule - Map changes = new HashMap(); - changes.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, "month|6"); - - // update the first dispostion action definition - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - List actionDefs = schedule.getDispositionActionDefinitions(); - assertEquals(2, actionDefs.size()); - System.out.println("Adding 6 months to period for 2nd step: " + actionDefs.get(1).getName()); - updateDispositionActionDefinition(schedule, actionDefs.get(1), changes); - - return null; - } - }); - - // make sure the disposition lifecycle asOf date has NOT been updated as the period was - // changed for a step other than the current one - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("deprecation") - public Object execute() throws Throwable - { - assertTrue(nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE)); - NodeRef ndNodeRef = nodeService.getChildAssocs(record, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(ndNodeRef); - - assertNotNull(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF)); - Date asOfDate = (Date)nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF); - System.out.println("Disposition as of: " + asOfDate); - - // make sure the as of date is a month in the future - Calendar calendar = Calendar.getInstance(); - calendar.add(Calendar.MONTH, 3); - assertEquals("Expecting the asOf date to be unchanged", asOfDate.getMonth(), calendar.get(Calendar.MONTH)); - - // Check for the search properties having been populated - checkSearchAspect(record); - - return null; - } - }); - - // change the disposition schedule to be event based rather than time based i.e. - // remove the period properties and supply 2 events in its place. - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // define changes for schedule - Map changes = new HashMap(); - changes.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, null); - List events = new ArrayList(2); - events.add("no_longer_needed"); - events.add("case_complete"); - changes.put(RecordsManagementModel.PROP_DISPOSITION_EVENT, (Serializable)events); - - // update the first dispostion action definition - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - List actionDefs = schedule.getDispositionActionDefinitions(); - assertEquals(2, actionDefs.size()); - System.out.println("Removing period and adding no_longer_needed and case_complete to 1st step: " + - actionDefs.get(0).getName()); - updateDispositionActionDefinition(schedule, actionDefs.get(0), changes); - - return null; - } - }); - - // make sure the disposition lifecycle asOf date has been reset and there are now - // events hanging off the nextdispositionaction node - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - assertTrue(nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE)); - NodeRef ndNodeRef = nodeService.getChildAssocs(record, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(ndNodeRef); - - Date asOfDate = (Date)nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF); - System.out.println("New disposition as of: " + asOfDate); - assertNull("Expecting asOfDate to be null", asOfDate); - - // make sure the 2 events are present - List events = nodeService.getChildAssocs(ndNodeRef, ASSOC_EVENT_EXECUTIONS, - RegexQNamePattern.MATCH_ALL); - assertEquals(2, events.size()); - NodeRef event1 = events.get(0).getChildRef(); - assertEquals("no_longer_needed", nodeService.getProperty(event1, PROP_EVENT_EXECUTION_NAME)); - NodeRef event2 = events.get(1).getChildRef(); - assertEquals("case_complete", nodeService.getProperty(event2, PROP_EVENT_EXECUTION_NAME)); - - // Check for the search properties having been populated - checkSearchAspect(record, false); - - return null; - } - }); - - // remove one of the events just added - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // define changes for schedule - Map changes = new HashMap(); - List events = new ArrayList(2); - events.add("case_complete"); - changes.put(RecordsManagementModel.PROP_DISPOSITION_EVENT, (Serializable)events); - - // update the first dispostion action definition - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - List actionDefs = schedule.getDispositionActionDefinitions(); - assertEquals(2, actionDefs.size()); - System.out.println("Removing no_longer_needed event from 1st step: " + - actionDefs.get(0).getName()); - updateDispositionActionDefinition(schedule, actionDefs.get(0), changes); - - return null; - } - }); - - // make sure the disposition lifecycle asOf date is still null and ensure there is only one event - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - assertTrue(nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE)); - NodeRef ndNodeRef = nodeService.getChildAssocs(record, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(ndNodeRef); - - Date asOfDate = (Date)nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF); - assertNull("Expecting asOfDate to be null", asOfDate); - - // make sure only 1 event is present - List events = nodeService.getChildAssocs(ndNodeRef, ASSOC_EVENT_EXECUTIONS, - RegexQNamePattern.MATCH_ALL); - assertEquals(1, events.size()); - NodeRef event = events.get(0).getChildRef(); - assertEquals("case_complete", nodeService.getProperty(event, PROP_EVENT_EXECUTION_NAME)); - - // Check for the search properties having been populated - checkSearchAspect(record, false); - - return null; - } - }); - - // change the action on the first step from 'cutoff' to 'retain' - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // define changes for schedule - Map changes = new HashMap(); - changes.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_NAME, "retain"); - - // update the first dispostion action definition - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - List actionDefs = schedule.getDispositionActionDefinitions(); - assertEquals(2, actionDefs.size()); - System.out.println("Changing action of 1st step from '" + - actionDefs.get(0).getName() + "' to 'retain'"); - updateDispositionActionDefinition(schedule, actionDefs.get(0), changes); - - return null; - } - }); - - // make sure the disposition lifecycle asOf date is still null, ensure there is still only one event - // and most importantly that the action name is now 'retain' - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - assertTrue(nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE)); - NodeRef ndNodeRef = nodeService.getChildAssocs(record, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(ndNodeRef); - - Date asOfDate = (Date)nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF); - assertNull("Expecting asOfDate to be null", asOfDate); - - // make sure only 1 event is present - List events = nodeService.getChildAssocs(ndNodeRef, ASSOC_EVENT_EXECUTIONS, - RegexQNamePattern.MATCH_ALL); - assertEquals(1, events.size()); - NodeRef event = events.get(0).getChildRef(); - assertEquals("case_complete", nodeService.getProperty(event, PROP_EVENT_EXECUTION_NAME)); - - String actionName = (String)nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION); - assertEquals("retain", actionName); - - // Check for the search properties having been populated - checkSearchAspect(record, false); - - return null; - } - }); - } - - private void updateDispositionActionDefinition(DispositionSchedule schedule, DispositionActionDefinition actionDefinition, Map actionDefinitionParams) - { - NodeRef nodeRef = actionDefinition.getNodeRef(); - Map before = nodeService.getProperties(nodeRef); - nodeService.addProperties(nodeRef, actionDefinitionParams); - Map after = nodeService.getProperties(nodeRef); - List updatedProps = determineChangedProps(before, after); - - refreshDispositionActionDefinition(nodeRef, updatedProps); - } - - private void refreshDispositionActionDefinition(NodeRef nodeRef, List updatedProps) - { - if (updatedProps != null) - { - Map params = new HashMap(); - params.put(BroadcastDispositionActionDefinitionUpdateAction.CHANGED_PROPERTIES, (Serializable)updatedProps); - rmActionService.executeRecordsManagementAction(nodeRef, BroadcastDispositionActionDefinitionUpdateAction.NAME, params); - } - - // Remove the unpublished update aspect - nodeService.removeAspect(nodeRef, ASPECT_UNPUBLISHED_UPDATE); - } - - private List determineChangedProps(Map oldProps, Map newProps) - { - List result = new ArrayList(); - for (QName qn : oldProps.keySet()) - { - if (newProps.get(qn) == null || - newProps.get(qn).equals(oldProps.get(qn)) == false) - { - result.add(qn); - } - } - for (QName qn : newProps.keySet()) - { - if (oldProps.get(qn) == null) - { - result.add(qn); - } - } - - return result; - } - - /** - * Tests the re-scheduling of disposition lifecycles when steps from the schedule are deleted - * (when using folder level disposition) - */ - public void testDispositionLifecycle_0318_reschedule_deletion_folderlevel() throws Exception - { - final NodeRef recordSeries = TestUtilities.getRecordSeries(rmService, nodeService, "Reports"); - setComplete(); - endTransaction(); - - // create a category - final NodeRef recordCategory = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - assertNotNull(recordSeries); - assertEquals("Reports", nodeService.getProperty(recordSeries, ContentModel.PROP_NAME)); - - return createRecordCategoryNode(recordSeries); - } - }); - - // define the disposition schedule for the category with several steps - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - assertNotNull(recordCategory); - - // define properties for both steps - Map step1 = new HashMap(); - step1.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_NAME, "cutoff"); - step1.put(RecordsManagementModel.PROP_DISPOSITION_DESCRIPTION, "Cutoff when no longer needed"); - step1.put(RecordsManagementModel.PROP_DISPOSITION_EVENT, "no_longer_needed"); - - Map step2 = new HashMap(); - step2.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_NAME, "transfer"); - step2.put(RecordsManagementModel.PROP_DISPOSITION_DESCRIPTION, "Transfer after 1 month"); - step2.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, "month|1"); - step2.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD_PROPERTY, PROP_DISPOSITION_AS_OF); - - Map step3 = new HashMap(); - step3.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_NAME, "destroy"); - step3.put(RecordsManagementModel.PROP_DISPOSITION_DESCRIPTION, "Destroy after 1 year"); - step3.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, "year|1"); - step3.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD_PROPERTY, PROP_DISPOSITION_AS_OF); - - // add the action definitions to the schedule - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - dispositionService.addDispositionActionDefinition(schedule, step1); - dispositionService.addDispositionActionDefinition(schedule, step2); - dispositionService.addDispositionActionDefinition(schedule, step3); - - return null; - } - }); - - // create first record folder - final NodeRef recordFolder1 = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - return createRecordFolder(recordCategory, "Folder1"); - } - }); - - // create second record folder - final NodeRef recordFolder2 = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - return createRecordFolder(recordCategory, "Folder2"); - } - }); - - // make sure the disposition lifecycle is present and correct - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - assertNotNull(recordFolder1); - assertNotNull(recordFolder2); - - assertTrue(nodeService.hasAspect(recordFolder1, ASPECT_DISPOSITION_LIFECYCLE)); - assertTrue(nodeService.hasAspect(recordFolder2, ASPECT_DISPOSITION_LIFECYCLE)); - NodeRef folder1NextAction = nodeService.getChildAssocs(recordFolder1, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(folder1NextAction); - NodeRef folder2NextAction = nodeService.getChildAssocs(recordFolder2, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(folder2NextAction); - - // make sure both folders are on the cutoff step - assertEquals("cutoff", nodeService.getProperty(folder1NextAction, PROP_DISPOSITION_ACTION)); - assertEquals("cutoff", nodeService.getProperty(folder2NextAction, PROP_DISPOSITION_ACTION)); - - // make sure both folders have 1 event - assertEquals(1, nodeService.getChildAssocs(folder1NextAction, ASSOC_EVENT_EXECUTIONS, - RegexQNamePattern.MATCH_ALL).size()); - assertEquals(1, nodeService.getChildAssocs(folder2NextAction, ASSOC_EVENT_EXECUTIONS, - RegexQNamePattern.MATCH_ALL).size()); - - // move folder 2 onto next step - Map params = new HashMap(3); - params.put(CompleteEventAction.PARAM_EVENT_NAME, "no_longer_needed"); - params.put(CompleteEventAction.PARAM_EVENT_COMPLETED_AT, new Date()); - params.put(CompleteEventAction.PARAM_EVENT_COMPLETED_BY, "gavinc"); - - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName()); - rmActionService.executeRecordsManagementAction(recordFolder2, "completeEvent", params); - rmActionService.executeRecordsManagementAction(recordFolder2, "cutoff"); - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); - - return null; - } - }); - - // check the second folder is at step 2 and then attempt to remove a step from the disposition schedule - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - NodeRef folder2NextAction = nodeService.getChildAssocs(recordFolder2, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(folder2NextAction); - assertEquals("transfer", (String)nodeService.getProperty(folder2NextAction, PROP_DISPOSITION_ACTION)); - - // check there are 3 steps to the schedule - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - List actionDefs = schedule.getDispositionActionDefinitions(); - assertEquals(3, actionDefs.size()); - - // attempt to remove step 1 from the schedule - try - { - dispositionService.removeDispositionActionDefinition(schedule, actionDefs.get(0)); - fail("Expecting the step deletion to be unsuccessful as record folders are present"); - } - catch (AlfrescoRuntimeException are) - { - // expected as steps are present, deletion not allowed - } - - return null; - } - }); - - // remove both record folders - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // remove record folders - nodeService.removeChild(recordCategory, recordFolder1); - nodeService.removeChild(recordCategory, recordFolder2); - return null; - } - }); - - // try removing last schedule step - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // make sure there are 3 steps - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - List actionDefs = schedule.getDispositionActionDefinitions(); - assertEquals(3, actionDefs.size()); - - // remove last step, should be successful this time - dispositionService.removeDispositionActionDefinition(schedule, actionDefs.get(2)); - - // make sure there are now 2 steps - schedule = dispositionService.getDispositionSchedule(recordCategory); - actionDefs = schedule.getDispositionActionDefinitions(); - assertEquals(2, actionDefs.size()); - - return null; - } - }); - - // *** NOTE: The commented out code below is potential tests for the step deletion behaviour *** - // *** we also need to add tests for deleting the step in the process where records or *** - // *** folders are on the last step i.e. what state should they be in if the last step *** - // *** is removed? *** - - /* - // check the second folder is at step 2 and remove the first step from the schedule - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - NodeRef folder2NextAction = nodeService.getChildAssocs(recordFolder2, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(folder2NextAction); - assertEquals("transfer", (String)nodeService.getProperty(folder2NextAction, PROP_DISPOSITION_ACTION)); - - // remove step 1 from the schedule - DispositionSchedule schedule = rmService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - List actionDefs = schedule.getDispositionActionDefinitions(); - assertEquals(3, actionDefs.size()); - System.out.println("Removing schedule step 1 named: " + actionDefs.get(0).getName()); - rmService.removeDispositionActionDefinition(schedule, actionDefs.get(0)); - - return null; - } - }); - - // make sure the next action for folder 1 has moved on and folder 2 is unchanged, then delete last step - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - NodeRef folder1NextAction = nodeService.getChildAssocs(recordFolder1, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(folder1NextAction); - NodeRef folder2NextAction = nodeService.getChildAssocs(recordFolder2, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(folder2NextAction); - - // make sure both folders are on the cutoff step - assertEquals("transfer", nodeService.getProperty(folder1NextAction, PROP_DISPOSITION_ACTION)); - assertEquals("transfer", nodeService.getProperty(folder2NextAction, PROP_DISPOSITION_ACTION)); - - // Check for the search properties having been populated - checkSearchAspect(folder1NextAction); - checkSearchAspect(folder2NextAction); - - // remove the step in the last position from the schedule - DispositionSchedule schedule = rmService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - List actionDefs = schedule.getDispositionActionDefinitions(); - assertEquals(2, actionDefs.size()); - System.out.println("Removing schedule last step named: " + actionDefs.get(1).getName()); - rmService.removeDispositionActionDefinition(schedule, actionDefs.get(1)); - - return null; - } - }); - - // check there were no changes, then remove the only remaining step - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - NodeRef folder1NextAction = nodeService.getChildAssocs(recordFolder1, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(folder1NextAction); - assertEquals("transfer", (String)nodeService.getProperty(folder1NextAction, PROP_DISPOSITION_ACTION)); - - NodeRef folder2NextAction = nodeService.getChildAssocs(recordFolder2, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(folder2NextAction); - assertEquals("transfer", (String)nodeService.getProperty(folder2NextAction, PROP_DISPOSITION_ACTION)); - - // remove last remaining step from the schedule - DispositionSchedule schedule = rmService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - List actionDefs = schedule.getDispositionActionDefinitions(); - assertEquals(1, actionDefs.size()); - System.out.println("Removing last remaining schedule step named: " + actionDefs.get(0).getName()); - rmService.removeDispositionActionDefinition(schedule, actionDefs.get(0)); - - return null; - } - }); - - // check there are no schedule steps left and that both folders no longer have the disposition lifecycle aspect, - // then add a new step - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - assertEquals(0, nodeService.getChildAssocs(recordFolder1, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).size()); - assertEquals(0, nodeService.getChildAssocs(recordFolder2, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).size()); - assertFalse(nodeService.hasAspect(recordFolder1, ASPECT_DISPOSITION_LIFECYCLE)); - assertFalse(nodeService.hasAspect(recordFolder2, ASPECT_DISPOSITION_LIFECYCLE)); - - // ensure schedule is empty - DispositionSchedule schedule = rmService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - List actionDefs = schedule.getDispositionActionDefinitions(); - assertEquals(0, actionDefs.size()); - - // add a new step - Map step1 = new HashMap(); - step1.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_NAME, "retain"); - step1.put(RecordsManagementModel.PROP_DISPOSITION_DESCRIPTION, "Retain for 25 years"); - step1.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, "year|25"); - rmService.addDispositionActionDefinition(schedule, step1); - - return null; - } - }); - - // check both folders now have the retain action - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - NodeRef folder1NextAction = nodeService.getChildAssocs(recordFolder1, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(folder1NextAction); - assertEquals("retain", (String)nodeService.getProperty(folder1NextAction, PROP_DISPOSITION_ACTION)); - assertNotNull(nodeService.getProperty(folder1NextAction, PROP_DISPOSITION_AS_OF)); - - NodeRef folder2NextAction = nodeService.getChildAssocs(recordFolder2, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(folder2NextAction); - assertEquals("retain", (String)nodeService.getProperty(folder2NextAction, PROP_DISPOSITION_ACTION)); - assertNotNull(nodeService.getProperty(folder2NextAction, PROP_DISPOSITION_AS_OF)); - - return null; - } - }); - */ - } - - /** - * Tests the re-scheduling of disposition lifecycles when steps from the schedule are deleted - * (when using record level disposition) - */ - public void testDispositionLifecycle_0318_reschedule_deletion_recordlevel() throws Exception - { - final NodeRef recordSeries = TestUtilities.getRecordSeries(rmService, nodeService, "Reports"); - setComplete(); - endTransaction(); - - // create a category - final NodeRef recordCategory = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - assertNotNull(recordSeries); - assertEquals("Reports", nodeService.getProperty(recordSeries, ContentModel.PROP_NAME)); - - return createRecordCategoryNode(recordSeries); - } - }); - - // define the disposition schedule for the category with several steps - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - assertNotNull(recordCategory); - - // get the disposition schedule and turn on record level disposition - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - nodeService.setProperty(schedule.getNodeRef(), PROP_RECORD_LEVEL_DISPOSITION, true); - - // define properties for both steps - Map step1 = new HashMap(); - step1.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_NAME, "cutoff"); - step1.put(RecordsManagementModel.PROP_DISPOSITION_DESCRIPTION, "Cutoff when no longer needed"); - step1.put(RecordsManagementModel.PROP_DISPOSITION_EVENT, "no_longer_needed"); - - Map step2 = new HashMap(); - step2.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_NAME, "transfer"); - step2.put(RecordsManagementModel.PROP_DISPOSITION_DESCRIPTION, "Transfer after 1 month"); - step2.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, "month|1"); - step2.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD_PROPERTY, PROP_DISPOSITION_AS_OF); - - Map step3 = new HashMap(); - step3.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_NAME, "destroy"); - step3.put(RecordsManagementModel.PROP_DISPOSITION_DESCRIPTION, "Destroy after 1 year"); - step3.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, "year|1"); - step3.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD_PROPERTY, PROP_DISPOSITION_AS_OF); - - // add the action definitions to the schedule - dispositionService.addDispositionActionDefinition(schedule, step1); - dispositionService.addDispositionActionDefinition(schedule, step2); - dispositionService.addDispositionActionDefinition(schedule, step3); - - return null; - } - }); - - // create first record folder - final NodeRef recordFolder = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - return createRecordFolder(recordCategory, "Record Folder"); - } - }); - - // create a record - final NodeRef record = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - assertNotNull(recordFolder); - - // Create the document - Map props = new HashMap(1); - props.put(ContentModel.PROP_NAME, "MyRecord.txt"); - NodeRef record = nodeService.createNode(recordFolder, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "MyRecord.txt"), - ContentModel.TYPE_CONTENT).getChildRef(); - - // Set the content - ContentWriter writer = contentService.getWriter(record, ContentModel.PROP_CONTENT, true); - writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); - writer.setEncoding("UTF-8"); - writer.putContent("There is some content in this record"); - - return record; - } - }); - - // make sure the disposition lifecycle is present and correct - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - assertNotNull(record); - - assertTrue(nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE)); - NodeRef recordNextAction = nodeService.getChildAssocs(record, ASSOC_NEXT_DISPOSITION_ACTION, - RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(recordNextAction); - - // make sure the record is on the cutoff step - assertEquals("cutoff", nodeService.getProperty(recordNextAction, PROP_DISPOSITION_ACTION)); - - // make sure the record has 1 event - assertEquals(1, nodeService.getChildAssocs(recordNextAction, ASSOC_EVENT_EXECUTIONS, - RegexQNamePattern.MATCH_ALL).size()); - - return null; - } - }); - - // check for steps in schedule then attempt to delete one - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // check there are 3 steps to the schedule - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - List actionDefs = schedule.getDispositionActionDefinitions(); - assertEquals(3, actionDefs.size()); - - // attempt to remove step 1 from the schedule - try - { - dispositionService.removeDispositionActionDefinition(schedule, actionDefs.get(0)); - fail("Expecting the step deletion to be unsuccessful as records are present"); - } - catch (AlfrescoRuntimeException are) - { - // expected as steps are present, deletion not allowed - } - - return null; - } - }); - - // remove the record (the folder can stay) - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // remove record folders - nodeService.removeChild(recordFolder, record); - return null; - } - }); - - // try removing last schedule step - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // make sure there are 3 steps - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - List actionDefs = schedule.getDispositionActionDefinitions(); - assertEquals(3, actionDefs.size()); - - // remove last step, should be successful this time - dispositionService.removeDispositionActionDefinition(schedule, actionDefs.get(2)); - - // make sure there are now 2 steps - schedule = dispositionService.getDispositionSchedule(recordCategory); - actionDefs = schedule.getDispositionActionDefinitions(); - assertEquals(2, actionDefs.size()); - - return null; - } - }); - } - - /** - * test a dispostion schedule being setup after a record folder and record - */ - public void testDispositionLifecycle_0318_existingfolders() throws Exception - { - final NodeRef recordSeries = TestUtilities.getRecordSeries(rmService, nodeService, "Reports"); - setComplete(); - endTransaction(); - - // create a category - final NodeRef recordCategory = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - assertNotNull(recordSeries); - assertEquals("Reports", nodeService.getProperty(recordSeries, ContentModel.PROP_NAME)); - - return createRecordCategoryNode(recordSeries); - } - }); - - // create a record folder - final NodeRef recordFolder = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - assertNotNull(recordCategory); - return createRecordFolder(recordCategory, "Folder1"); - } - }); - - // define the disposition schedule for the category (Cut off monthly, hold 1 month, then destroy) - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - assertNotNull(recordFolder); - - // define properties for both steps - Map step1 = new HashMap(); - step1.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_NAME, "cutoff"); - step1.put(RecordsManagementModel.PROP_DISPOSITION_DESCRIPTION, "Cutoff after 1 month"); - step1.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, "month|1"); - - Map step2 = new HashMap(); - step2.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_NAME, "destroy"); - step2.put(RecordsManagementModel.PROP_DISPOSITION_DESCRIPTION, "Destroy after 1 month"); - step2.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, "month|1"); - step2.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD_PROPERTY, PROP_CUT_OFF_DATE); - - // add the action definitions to the schedule - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - - NodeRef temp = dispositionService.addDispositionActionDefinition(schedule, step1).getNodeRef(); - List updatedProps = new ArrayList(step1.keySet()); - refreshDispositionActionDefinition(temp, updatedProps); - - temp = dispositionService.addDispositionActionDefinition(schedule, step2).getNodeRef(); - updatedProps = new ArrayList(step2.keySet()); - refreshDispositionActionDefinition(temp, updatedProps); - - return null; - } - }); - - // make sure the disposition lifecycle is present and correct - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("deprecation") - public Object execute() throws Throwable - { - assertNotNull(recordFolder); - - DispositionAction da = dispositionService.getNextDispositionAction(recordFolder); - assertNotNull(da); - - assertNotNull(da.getDispositionActionDefinition()); - assertNotNull(da.getDispositionActionDefinition().getId()); - assertEquals("cutoff", da.getName()); - Date asOfDate = da.getAsOfDate(); - assertNotNull(asOfDate); - - // make sure the as of date is a month in the future - Calendar cal = Calendar.getInstance(); - cal.add(Calendar.MONTH, 1); - int monthThen = cal.get(Calendar.MONTH); - assertEquals(asOfDate.getMonth(), monthThen); - - // make sure there aren't any events - assertEquals(0, da.getEventCompletionDetails().size()); - - // Check for the search properties having been populated - checkSearchAspect(recordFolder); - - return null; - } - }); - } - - /** - * Test the updating of a disposition schedule using folder level disposition - */ - public void testFolderLevelDispositionScheduleUpdate() throws Exception - { - final NodeRef recordSeries = TestUtilities.getRecordSeries(rmService, nodeService, "Reports"); - setComplete(); - endTransaction(); - - // create a category - final NodeRef recordCategory = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - assertNotNull(recordSeries); - assertEquals("Reports", nodeService.getProperty(recordSeries, ContentModel.PROP_NAME)); - - return createRecordCategoryNode(recordSeries); - } - }); - - // define the disposition schedule for the category (Cut off monthly, hold 1 month, then destroy) - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - assertNotNull(recordCategory); - - // get the disposition schedule and turn on record level disposition - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - nodeService.setProperty(schedule.getNodeRef(), PROP_DISPOSITION_INSTRUCTIONS, "Cutoff after 1 month then destroy after 1 month"); - nodeService.setProperty(schedule.getNodeRef(), PROP_DISPOSITION_AUTHORITY, "Alfresco"); - - return null; - } - }); - - // create a record folder - final NodeRef recordFolder = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - return createRecordFolder(recordCategory, "Folder1"); - } - }); - - // check the created folder has the correctly populated search aspect, then update the schedule - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // check the folder has the search aspect - assertNotNull(recordFolder); - checkSearchAspect(recordFolder, false); - - // update the disposition schedule - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - nodeService.setProperty(schedule.getNodeRef(), PROP_DISPOSITION_INSTRUCTIONS, "Cutoff immediately when case is closed then destroy after 1 year"); - nodeService.setProperty(schedule.getNodeRef(), PROP_DISPOSITION_AUTHORITY, "DoD"); - - return null; - } - }); - - // check the search aspect has been kept in sync - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // check the folder has the search aspect - checkSearchAspect(recordFolder, false); - - return null; - } - }); - } - - /** - * Test the updating of a disposition schedule using record level disposition - */ - public void testRecordLevelDispositionScheduleUpdate() throws Exception - { - final NodeRef recordSeries = TestUtilities.getRecordSeries(rmService, nodeService, "Reports"); - setComplete(); - endTransaction(); - - // create a category - final NodeRef recordCategory = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - assertNotNull(recordSeries); - assertEquals("Reports", nodeService.getProperty(recordSeries, ContentModel.PROP_NAME)); - - return createRecordCategoryNode(recordSeries); - } - }); - - // define the disposition schedule for the category (Cut off monthly, hold 1 month, then destroy) - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - assertNotNull(recordCategory); - - // get the disposition schedule and turn on record level disposition - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - nodeService.setProperty(schedule.getNodeRef(), PROP_DISPOSITION_INSTRUCTIONS, "Cutoff after 1 month then destroy after 1 month"); - nodeService.setProperty(schedule.getNodeRef(), PROP_DISPOSITION_AUTHORITY, "Alfresco"); - nodeService.setProperty(schedule.getNodeRef(), PROP_RECORD_LEVEL_DISPOSITION, true); - - return null; - } - }); - - // create a record folder - final NodeRef recordFolder = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - return createRecordFolder(recordCategory, "Folder1"); - } - }); - - // create a record - final NodeRef record = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - assertNotNull(recordFolder); - - // Create the document - Map props = new HashMap(1); - props.put(ContentModel.PROP_NAME, "MyRecord.txt"); - NodeRef record = nodeService.createNode(recordFolder, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "MyRecord.txt"), - ContentModel.TYPE_CONTENT).getChildRef(); - - // Set the content - ContentWriter writer = contentService.getWriter(record, ContentModel.PROP_CONTENT, true); - writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); - writer.setEncoding("UTF-8"); - writer.putContent("There is some content in this record"); - - return record; - } - }); - - // check the created folder has the correctly populated search aspect, then update the schedule - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // check the record has the search aspect - assertNotNull(record); - checkSearchAspect(record, false); - - // update the disposition schedule - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(schedule); - nodeService.setProperty(schedule.getNodeRef(), PROP_DISPOSITION_INSTRUCTIONS, "Cutoff immediately when case is closed then destroy after 1 year"); - nodeService.setProperty(schedule.getNodeRef(), PROP_DISPOSITION_AUTHORITY, "DoD"); - - return null; - } - }); - - // check the search aspect has been kept in sync - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // check the record has the search aspect - checkSearchAspect(record, false); - - return null; - } - }); - } - - public void testUnCutoff() - { - final NodeRef recordCategory = TestUtilities.getRecordCategory(rmService, nodeService, "Reports", "AIS Audit Records"); - setComplete(); - endTransaction(); - - final NodeRef recordFolder = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - - assertNotNull(recordCategory); - assertEquals("AIS Audit Records", nodeService.getProperty(recordCategory, ContentModel.PROP_NAME)); - - return createRecordFolder(recordCategory, "March AIS Audit Records"); - } - }); - - final NodeRef recordOne = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - return createRecord(recordFolder); - } - }); - - final Calendar calendar = Calendar.getInstance(); - calendar.set(Calendar.HOUR, 0); - calendar.set(Calendar.MINUTE, 0); - calendar.set(Calendar.SECOND, 0); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - TestUtilities.declareRecord(recordOne, unprotectedNodeService, rmActionService); - - // Clock the asOf date back to ensure eligibility - NodeRef ndNodeRef = nodeService.getChildAssocs(recordFolder, ASSOC_NEXT_DISPOSITION_ACTION, RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - Date nowDate = calendar.getTime(); - assertFalse(nowDate.equals(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF))); - Map params = new HashMap(1); - params.put(EditDispositionActionAsOfDateAction.PARAM_AS_OF_DATE, nowDate); - rmActionService.executeRecordsManagementAction(recordFolder, "editDispositionActionAsOfDate", params); - assertTrue(nowDate.equals(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF))); - - // Cut off - rmActionService.executeRecordsManagementAction(recordFolder, "cutoff", null); - - // Check that everything appears to be cutoff - assertTrue(nodeService.hasAspect(recordFolder, ASPECT_CUT_OFF)); - List records = rmService.getRecords(recordFolder); - for (NodeRef record : records) - { - assertTrue(nodeService.hasAspect(record, ASPECT_CUT_OFF)); - } - DispositionAction da = dispositionService.getNextDispositionAction(recordFolder); - assertNotNull(da); - assertFalse("cutoff".equals(da.getName())); - checkLastDispositionAction(recordFolder, "cutoff", 1); - - // Revert the cutoff - rmActionService.executeRecordsManagementAction(recordFolder, "unCutoff", null); - - // Check that everything has been reverted - assertFalse(nodeService.hasAspect(recordFolder, ASPECT_CUT_OFF)); - records = rmService.getRecords(recordFolder); - for (NodeRef record : records) - { - assertFalse(nodeService.hasAspect(record, ASPECT_CUT_OFF)); - } - da = dispositionService.getNextDispositionAction(recordFolder); - assertNotNull(da); - assertTrue("cutoff".equals(da.getName())); - assertNull(da.getStartedAt()); - assertNull(da.getStartedBy()); - assertNull(da.getCompletedAt()); - assertNull(da.getCompletedBy()); - List history = dispositionService.getCompletedDispositionActions(recordFolder); - assertNotNull(history); - assertEquals(0, history.size()); - - return null; - } - }); - - } - - private void checkLastDispositionAction(NodeRef nodeRef, String daName, int expectedCount) - { - // Check the previous action details - List history = dispositionService.getCompletedDispositionActions(nodeRef); - assertNotNull(history); - assertEquals(expectedCount, history.size()); - DispositionAction lastDA = history.get(history.size()-1); - assertEquals(daName, lastDA.getName()); - assertNotNull(lastDA.getStartedAt()); - assertNotNull(lastDA.getStartedBy()); - assertNotNull(lastDA.getCompletedAt()); - assertNotNull(lastDA.getCompletedBy()); - // Check the "get last" method - lastDA = dispositionService.getLastCompletedDispostionAction(nodeRef); - assertEquals(daName, lastDA.getName()); - } - - public void testFreeze() throws Exception - { - final NodeRef recordCategory = TestUtilities.getRecordCategory(rmService, nodeService, "Reports", "AIS Audit Records"); - assertNotNull(recordCategory); - assertEquals("AIS Audit Records", this.nodeService.getProperty(recordCategory, ContentModel.PROP_NAME)); - - // Before we start just remove any outstanding holds - final NodeRef rootNode = this.rmService.getFilePlan(recordCategory); - List tempAssocs = this.nodeService.getChildAssocs(rootNode, ASSOC_HOLDS, RegexQNamePattern.MATCH_ALL); - for (ChildAssociationRef tempAssoc : tempAssocs) - { - this.nodeService.deleteNode(tempAssoc.getChildRef()); - } - - final NodeRef recordFolder = createRecordFolder(recordCategory, "March AIS Audit Records"); - - setComplete(); - endTransaction(); - - final NodeRef recordOne = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - return createRecord(recordFolder, "one.txt"); - } - }); - final NodeRef recordTwo = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - return createRecord(recordFolder, "two.txt"); - } - }); - final NodeRef recordThree = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - return createRecord(recordFolder, "three.txt"); - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - assertTrue(nodeService.hasAspect(recordOne, ASPECT_RECORD)); - assertTrue(nodeService.hasAspect(recordOne, ASPECT_FILE_PLAN_COMPONENT)); - - // Freeze the record - Map params = new HashMap(1); - params.put(FreezeAction.PARAM_REASON, "reason1"); - rmActionService.executeRecordsManagementAction(recordOne, "freeze", params); - - return null; - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // Check the hold exists - List holdAssocs = nodeService.getChildAssocs(rootNode, ASSOC_HOLDS, RegexQNamePattern.MATCH_ALL); - assertNotNull(holdAssocs); - assertEquals(1, holdAssocs.size()); - NodeRef holdNodeRef = holdAssocs.get(0).getChildRef(); - assertEquals("reason1", nodeService.getProperty(holdNodeRef, PROP_HOLD_REASON)); - List freezeAssocs = nodeService.getChildAssocs(holdNodeRef); - assertNotNull(freezeAssocs); - assertEquals(1, freezeAssocs.size()); - - // Check the nodes are frozen - assertTrue(nodeService.hasAspect(recordOne, ASPECT_FROZEN)); - assertNotNull(nodeService.getProperty(recordOne, PROP_FROZEN_AT)); - assertNotNull(nodeService.getProperty(recordOne, PROP_FROZEN_BY)); - assertFalse(nodeService.hasAspect(recordTwo, ASPECT_FROZEN)); - assertFalse(nodeService.hasAspect(recordThree, ASPECT_FROZEN)); - - // check the records have the hold reason reflected on the search aspect - assertEquals("reason1", nodeService.getProperty(recordOne, RecordsManagementSearchBehaviour.PROP_RS_HOLD_REASON)); - assertNull(nodeService.getProperty(recordTwo, RecordsManagementSearchBehaviour.PROP_RS_HOLD_REASON)); - assertNull(nodeService.getProperty(recordThree, RecordsManagementSearchBehaviour.PROP_RS_HOLD_REASON)); - - // Update the freeze reason - Map params = new HashMap(1); - params.put(FreezeAction.PARAM_REASON, "reason1changed"); - rmActionService.executeRecordsManagementAction(holdNodeRef, "editHoldReason", params); - - // Check the hold has been updated - String updatedHoldReason = (String)nodeService.getProperty(holdNodeRef, PROP_HOLD_REASON); - assertEquals("reason1changed", updatedHoldReason); - - return null; - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // check the search fields on the records have also been updated - assertEquals("reason1changed", nodeService.getProperty(recordOne, RecordsManagementSearchBehaviour.PROP_RS_HOLD_REASON)); - assertNull(nodeService.getProperty(recordTwo, RecordsManagementSearchBehaviour.PROP_RS_HOLD_REASON)); - assertNull(nodeService.getProperty(recordThree, RecordsManagementSearchBehaviour.PROP_RS_HOLD_REASON)); - - // Freeze a number of records - Map params = new HashMap(1); - params.put(FreezeAction.PARAM_REASON, "reason2"); - List records = new ArrayList(2); - records.add(recordOne); - records.add(recordTwo); - records.add(recordThree); - rmActionService.executeRecordsManagementAction(records, "freeze", params); - - return null; - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // Check the holds exist - List holdAssocs = nodeService.getChildAssocs(rootNode, ASSOC_HOLDS, RegexQNamePattern.MATCH_ALL); - assertNotNull(holdAssocs); - assertEquals(2, holdAssocs.size()); - for (ChildAssociationRef holdAssoc : holdAssocs) - { - String reason = (String)nodeService.getProperty(holdAssoc.getChildRef(), PROP_HOLD_REASON); - if (reason.equals("reason2") == true) - { - List freezeAssocs = nodeService.getChildAssocs(holdAssoc.getChildRef()); - assertNotNull(freezeAssocs); - assertEquals(3, freezeAssocs.size()); - } - else if (reason.equals("reason1changed") == true) - { - List freezeAssocs = nodeService.getChildAssocs(holdAssoc.getChildRef()); - assertNotNull(freezeAssocs); - assertEquals(1, freezeAssocs.size()); - } - } - - // Check the nodes are frozen - final List testRecords = Arrays.asList(new NodeRef[]{recordOne, recordTwo, recordThree}); - for (NodeRef nr : testRecords) - { - assertTrue(nodeService.hasAspect(nr, ASPECT_FROZEN)); - assertNotNull(nodeService.getProperty(nr, PROP_FROZEN_AT)); - assertNotNull(nodeService.getProperty(nr, PROP_FROZEN_BY)); - assertNotNull(nodeService.getProperty(nr, RecordsManagementSearchBehaviour.PROP_RS_HOLD_REASON)); - } - - // Unfreeze a node - rmActionService.executeRecordsManagementAction(recordThree, "unfreeze"); - - return null; - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // Check the holds - List holdAssocs = nodeService.getChildAssocs(rootNode, ASSOC_HOLDS, RegexQNamePattern.MATCH_ALL); - assertNotNull(holdAssocs); - assertEquals(2, holdAssocs.size()); - for (ChildAssociationRef holdAssoc : holdAssocs) - { - String reason = (String)nodeService.getProperty(holdAssoc.getChildRef(), PROP_HOLD_REASON); - if (reason.equals("reason2") == true) - { - List freezeAssocs = nodeService.getChildAssocs(holdAssoc.getChildRef()); - assertNotNull(freezeAssocs); - assertEquals(2, freezeAssocs.size()); - } - else if (reason.equals("reason1changed") == true) - { - List freezeAssocs = nodeService.getChildAssocs(holdAssoc.getChildRef()); - assertNotNull(freezeAssocs); - assertEquals(1, freezeAssocs.size()); - } - } - - // Check the nodes are frozen - assertTrue(nodeService.hasAspect(recordOne, ASPECT_FROZEN)); - assertNotNull(nodeService.getProperty(recordOne, PROP_FROZEN_AT)); - assertNotNull(nodeService.getProperty(recordOne, PROP_FROZEN_BY)); - assertEquals("reason2", nodeService.getProperty(recordOne, RecordsManagementSearchBehaviour.PROP_RS_HOLD_REASON)); - assertTrue(nodeService.hasAspect(recordTwo, ASPECT_FROZEN)); - assertNotNull(nodeService.getProperty(recordTwo, PROP_FROZEN_AT)); - assertNotNull(nodeService.getProperty(recordTwo, PROP_FROZEN_BY)); - assertEquals("reason2", nodeService.getProperty(recordTwo, RecordsManagementSearchBehaviour.PROP_RS_HOLD_REASON)); - assertFalse(nodeService.hasAspect(recordThree, ASPECT_FROZEN)); - assertNull(nodeService.getProperty(recordThree, RecordsManagementSearchBehaviour.PROP_RS_HOLD_REASON)); - - return null; - } - }); - - // Put the relinquish hold request into its own transaction - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // Check the holds - List holdAssocs = nodeService.getChildAssocs(rootNode, ASSOC_HOLDS, RegexQNamePattern.MATCH_ALL); - assertNotNull(holdAssocs); - assertEquals(2, holdAssocs.size()); - // Relinquish the first hold - NodeRef holdNodeRef = holdAssocs.get(0).getChildRef(); - assertEquals("reason1changed", nodeService.getProperty(holdNodeRef, PROP_HOLD_REASON)); - - rmActionService.executeRecordsManagementAction(holdNodeRef, "relinquishHold"); - - // Check the holds - holdAssocs = nodeService.getChildAssocs(rootNode, ASSOC_HOLDS, RegexQNamePattern.MATCH_ALL); - assertNotNull(holdAssocs); - assertEquals(1, holdAssocs.size()); - holdNodeRef = holdAssocs.get(0).getChildRef(); - assertEquals("reason2", nodeService.getProperty(holdNodeRef, PROP_HOLD_REASON)); - List freezeAssocs = nodeService.getChildAssocs(holdNodeRef); - assertNotNull(freezeAssocs); - assertEquals(2, freezeAssocs.size()); - - return null; - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // Check the nodes are frozen - assertTrue(nodeService.hasAspect(recordOne, ASPECT_FROZEN)); - assertNotNull(nodeService.getProperty(recordOne, PROP_FROZEN_AT)); - assertNotNull(nodeService.getProperty(recordOne, PROP_FROZEN_BY)); - // TODO: record one is still linked to a hold so should have the original hold reason - // on the search aspect but we're presuming just one hold for now so the search hold - // reason will remain unchanged - assertEquals("reason2", nodeService.getProperty(recordOne, RecordsManagementSearchBehaviour.PROP_RS_HOLD_REASON)); - assertTrue(nodeService.hasAspect(recordTwo, ASPECT_FROZEN)); - assertNotNull(nodeService.getProperty(recordTwo, PROP_FROZEN_AT)); - assertNotNull(nodeService.getProperty(recordTwo, PROP_FROZEN_BY)); - assertEquals("reason2", nodeService.getProperty(recordTwo, RecordsManagementSearchBehaviour.PROP_RS_HOLD_REASON)); - assertFalse(nodeService.hasAspect(recordThree, ASPECT_FROZEN)); - assertNull(nodeService.getProperty(recordThree, RecordsManagementSearchBehaviour.PROP_RS_HOLD_REASON)); - - // Unfreeze - rmActionService.executeRecordsManagementAction(recordOne, "unfreeze"); - - return null; - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // Check the holds - List holdAssocs = nodeService.getChildAssocs(rootNode, ASSOC_HOLDS, RegexQNamePattern.MATCH_ALL); - assertNotNull(holdAssocs); - assertEquals(1, holdAssocs.size()); - NodeRef holdNodeRef = holdAssocs.get(0).getChildRef(); - assertEquals("reason2", nodeService.getProperty(holdNodeRef, PROP_HOLD_REASON)); - List freezeAssocs = nodeService.getChildAssocs(holdNodeRef); - assertNotNull(freezeAssocs); - assertEquals(1, freezeAssocs.size()); - - // Check the nodes are frozen - assertFalse(nodeService.hasAspect(recordOne, ASPECT_FROZEN)); - assertNull(nodeService.getProperty(recordOne, RecordsManagementSearchBehaviour.PROP_RS_HOLD_REASON)); - assertTrue(nodeService.hasAspect(recordTwo, ASPECT_FROZEN)); - assertNotNull(nodeService.getProperty(recordTwo, PROP_FROZEN_AT)); - assertNotNull(nodeService.getProperty(recordTwo, PROP_FROZEN_BY)); - assertEquals("reason2", nodeService.getProperty(recordTwo, RecordsManagementSearchBehaviour.PROP_RS_HOLD_REASON)); - assertFalse(nodeService.hasAspect(recordThree, ASPECT_FROZEN)); - assertNull(nodeService.getProperty(recordThree, RecordsManagementSearchBehaviour.PROP_RS_HOLD_REASON)); - - // Unfreeze - rmActionService.executeRecordsManagementAction(recordTwo, "unfreeze"); - - return null; - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // Check the holds - List holdAssocs = nodeService.getChildAssocs(rootNode, ASSOC_HOLDS, RegexQNamePattern.MATCH_ALL); - assertNotNull(holdAssocs); - assertEquals(0, holdAssocs.size()); - - // Check the nodes are unfrozen - assertFalse(nodeService.hasAspect(recordOne, ASPECT_FROZEN)); - assertFalse(nodeService.hasAspect(recordTwo, ASPECT_FROZEN)); - assertFalse(nodeService.hasAspect(recordThree, ASPECT_FROZEN)); - - // check the search hold reason is null on all records - assertNull(nodeService.getProperty(recordOne, RecordsManagementSearchBehaviour.PROP_RS_HOLD_REASON)); - assertNull(nodeService.getProperty(recordTwo, RecordsManagementSearchBehaviour.PROP_RS_HOLD_REASON)); - assertNull(nodeService.getProperty(recordThree, RecordsManagementSearchBehaviour.PROP_RS_HOLD_REASON)); - - return null; - } - }); - } - - public void testAutoSuperseded() - { - final NodeRef recordCategory = TestUtilities.getRecordCategory(rmService, nodeService, "Civilian Files", "Employee Performance File System Records"); - assertNotNull(recordCategory); - assertEquals("Employee Performance File System Records", this.nodeService.getProperty(recordCategory, ContentModel.PROP_NAME)); - - final NodeRef recordFolder = createRecordFolder(recordCategory, "Test Record Folder"); - - // Before we start just remove any outstanding transfers - final NodeRef rootNode = this.rmService.getFilePlan(recordCategory); - List tempAssocs = this.nodeService.getChildAssocs(rootNode, ASSOC_TRANSFERS, RegexQNamePattern.MATCH_ALL); - for (ChildAssociationRef tempAssoc : tempAssocs) - { - this.nodeService.deleteNode(tempAssoc.getChildRef()); - } - - setComplete(); - endTransaction(); - - final NodeRef recordOne = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - return createRecord(recordFolder, "one.txt"); - } - }); - final NodeRef recordTwo = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - return createRecord(recordFolder, "two.txt"); - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - assertTrue(nodeService.hasAspect(recordOne, ASPECT_RECORD)); - - TestUtilities.declareRecord(recordOne, unprotectedNodeService, rmActionService); - TestUtilities.declareRecord(recordTwo, unprotectedNodeService, rmActionService); - - return null; - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - - DispositionAction da = dispositionService.getNextDispositionAction(recordTwo); - assertNotNull(da); - assertEquals("cutoff", da.getName()); - assertFalse(da.isEventsEligible()); - List events = da.getEventCompletionDetails(); - assertNotNull(events); - assertEquals(1, events.size()); - EventCompletionDetails event = events.get(0); - assertEquals("superseded", event.getEventName()); - assertFalse(event.isEventComplete()); - assertNull(event.getEventCompletedAt()); - assertNull(event.getEventCompletedBy()); - - rmAdminService.addCustomReference(recordOne, recordTwo, QName.createQName(RecordsManagementCustomModel.RM_CUSTOM_URI, "supersedes")); - - return null; - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - DispositionAction da = dispositionService.getNextDispositionAction(recordTwo); - assertNotNull(da); - assertEquals("cutoff", da.getName()); - assertTrue(da.isEventsEligible()); - List events = da.getEventCompletionDetails(); - assertNotNull(events); - assertEquals(1, events.size()); - EventCompletionDetails event = events.get(0); - assertEquals("superseded", event.getEventName()); - assertTrue(event.isEventComplete()); - assertNotNull(event.getEventCompletedAt()); - assertNotNull(event.getEventCompletedBy()); - - return null; - } - }); - } - - public void testVersioned() - { - final NodeRef recordCategory = TestUtilities.getRecordCategory(rmService, nodeService, "Civilian Files", "Employee Performance File System Records"); - assertNotNull(recordCategory); - assertEquals("Employee Performance File System Records", this.nodeService.getProperty(recordCategory, ContentModel.PROP_NAME)); - - final NodeRef recordFolder = createRecordFolder(recordCategory, "Test Record Folder"); - - // Before we start just remove any outstanding transfers - final NodeRef rootNode = this.rmService.getFilePlan(recordCategory); - List tempAssocs = this.nodeService.getChildAssocs(rootNode, ASSOC_TRANSFERS, RegexQNamePattern.MATCH_ALL); - for (ChildAssociationRef tempAssoc : tempAssocs) - { - this.nodeService.deleteNode(tempAssoc.getChildRef()); - } - - setComplete(); - endTransaction(); - - final NodeRef recordOne = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - return createRecord(recordFolder, "one.txt"); - } - }); - final NodeRef recordTwo = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - return createRecord(recordFolder, "two.txt"); - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - assertTrue(nodeService.hasAspect(recordOne, ASPECT_RECORD)); - - TestUtilities.declareRecord(recordOne, unprotectedNodeService, rmActionService); - TestUtilities.declareRecord(recordTwo, unprotectedNodeService, rmActionService); - - assertFalse(nodeService.hasAspect(recordOne, ASPECT_VERSIONED_RECORD)); - - rmAdminService.addCustomReference(recordOne, recordTwo, QName.createQName(RecordsManagementCustomModel.RM_CUSTOM_URI, "versions")); - - return null; - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - assertTrue(nodeService.hasAspect(recordOne, ASPECT_VERSIONED_RECORD)); - - rmAdminService.removeCustomReference(recordOne, recordTwo, QName.createQName(RecordsManagementCustomModel.RM_CUSTOM_URI, "versions")); - - return null; - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - assertFalse(nodeService.hasAspect(recordOne, ASPECT_VERSIONED_RECORD)); - - return null; - } - }); - } - - public void testDispositionLifecycle_0430_02_transfer() throws Exception - { - final NodeRef recordCategory = TestUtilities.getRecordCategory(rmService, nodeService, "Civilian Files", "Foreign Employee Award Files"); - assertNotNull(recordCategory); - assertEquals("Foreign Employee Award Files", this.nodeService.getProperty(recordCategory, ContentModel.PROP_NAME)); - - final NodeRef recordFolder = createRecordFolder(recordCategory, "Test Record Folder"); - - // Before we start just remove any outstanding transfers - final NodeRef rootNode = this.rmService.getFilePlan(recordCategory); - List tempAssocs = this.nodeService.getChildAssocs(rootNode, ASSOC_TRANSFERS, RegexQNamePattern.MATCH_ALL); - for (ChildAssociationRef tempAssoc : tempAssocs) - { - this.nodeService.deleteNode(tempAssoc.getChildRef()); - } - - setComplete(); - endTransaction(); - - final NodeRef recordOne = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - return createRecord(recordFolder, "one.txt"); - } - }); - final NodeRef recordTwo = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - return createRecord(recordFolder, "two.txt"); - } - }); - final NodeRef recordThree = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - // Create the document - Map props = new HashMap(1); - props.put(ContentModel.PROP_NAME, "three.pdf"); - NodeRef recordThree = nodeService.createNode(recordFolder, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "three.pdf"), - ContentModel.TYPE_CONTENT, - props).getChildRef(); - - // Set the content - ContentWriter writer = contentService.getWriter(recordOne, ContentModel.PROP_CONTENT, true); - writer.setMimetype(MimetypeMap.MIMETYPE_PDF); - writer.setEncoding("UTF-8"); - writer.putContent("asdas"); - - return recordThree; - } - }); - - final DispositionAction da = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public DispositionAction execute() throws Throwable - { - // Declare the records - TestUtilities.declareRecord(recordOne, unprotectedNodeService, rmActionService); - TestUtilities.declareRecord(recordTwo, unprotectedNodeService, rmActionService); - TestUtilities.declareRecord(recordThree, unprotectedNodeService, rmActionService); - - // Cutoff - Map params = new HashMap(3); - params.put(CompleteEventAction.PARAM_EVENT_NAME, "case_complete"); - params.put(CompleteEventAction.PARAM_EVENT_COMPLETED_AT, new Date()); - params.put(CompleteEventAction.PARAM_EVENT_COMPLETED_BY, "roy"); - rmActionService.executeRecordsManagementAction(recordFolder, "completeEvent", params); - rmActionService.executeRecordsManagementAction(recordFolder, "cutoff"); - - checkLastDispositionAction(recordFolder, "cutoff", 1); - - DispositionAction da = dispositionService.getNextDispositionAction(recordFolder); - assertNotNull(da); - assertEquals("transfer", da.getName()); - - assertFalse(nodeService.hasAspect(recordFolder, ASPECT_TRANSFERRED)); - - return da; - } - }); - - // Do the transfer - final Calendar calendar = Calendar.getInstance(); - calendar.set(Calendar.HOUR, 0); - calendar.set(Calendar.MINUTE, 0); - calendar.set(Calendar.SECOND, 0); - - final Object actionResult = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // Clock the asOf date back to ensure eligibility - Date nowDate = calendar.getTime(); - assertFalse(nowDate.equals(nodeService.getProperty(da.getNodeRef(), PROP_DISPOSITION_AS_OF))); - Map params = new HashMap(1); - params.put(EditDispositionActionAsOfDateAction.PARAM_AS_OF_DATE, nowDate); - rmActionService.executeRecordsManagementAction(recordFolder, "editDispositionActionAsOfDate", params); - assertTrue(nowDate.equals(nodeService.getProperty(da.getNodeRef(), PROP_DISPOSITION_AS_OF))); - - return rmActionService.executeRecordsManagementAction(recordFolder, "transfer", null); - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - assertFalse(nodeService.hasAspect(recordFolder, ASPECT_TRANSFERRED)); - assertFalse(nodeService.hasAspect(recordOne, ASPECT_TRANSFERRED)); - assertFalse(nodeService.hasAspect(recordTwo, ASPECT_TRANSFERRED)); - assertFalse(nodeService.hasAspect(recordThree, ASPECT_TRANSFERRED)); - - // Check that the next disposition action is still in the correct state - DispositionAction da = dispositionService.getNextDispositionAction(recordFolder); - assertNotNull(da); - assertEquals("transfer", da.getName()); - assertNotNull(da.getStartedAt()); - assertNotNull(da.getStartedBy()); - assertNull(da.getCompletedAt()); - assertNull(da.getCompletedBy()); - - checkLastDispositionAction(recordFolder, "cutoff", 1); - - // Check that the transfer object is created - assertNotNull(rootNode); - List assocs = nodeService.getChildAssocs(rootNode, ASSOC_TRANSFERS, RegexQNamePattern.MATCH_ALL); - assertNotNull(assocs); - assertEquals(1, assocs.size()); - NodeRef transferNodeRef = assocs.get(0).getChildRef(); - assertEquals(TYPE_TRANSFER, nodeService.getType(transferNodeRef)); - assertTrue(((Boolean)nodeService.getProperty(transferNodeRef, PROP_TRANSFER_PDF_INDICATOR)).booleanValue()); - assertEquals("Offline Storage", (String)nodeService.getProperty(transferNodeRef, PROP_TRANSFER_LOCATION)); - assertNotNull(actionResult); - assertEquals(transferNodeRef, ((RecordsManagementActionResult)actionResult).getValue()); - List children = nodeService.getChildAssocs(transferNodeRef, ASSOC_TRANSFERRED, RegexQNamePattern.MATCH_ALL); - assertNotNull(children); - assertEquals(1, children.size()); - - - // Complete the transfer - rmActionService.executeRecordsManagementAction(assocs.get(0).getChildRef(), "transferComplete"); - - // Check nodes have been marked correctly - assertTrue(nodeService.hasAspect(recordFolder, ASPECT_TRANSFERRED)); - assertTrue(nodeService.hasAspect(recordOne, ASPECT_TRANSFERRED)); - assertTrue(nodeService.hasAspect(recordTwo, ASPECT_TRANSFERRED)); - assertTrue(nodeService.hasAspect(recordThree, ASPECT_TRANSFERRED)); - - // Check the transfer object is deleted - assocs = nodeService.getChildAssocs(rootNode, ASSOC_TRANSFERS, RegexQNamePattern.MATCH_ALL); - assertNotNull(assocs); - assertEquals(0, assocs.size()); - - // Check the disposition action has been moved on - da = dispositionService.getNextDispositionAction(recordFolder); - assertNotNull(da); - assertEquals("transfer", da.getName()); - assertNull(da.getStartedAt()); - assertNull(da.getStartedBy()); - assertNull(da.getCompletedAt()); - assertNull(da.getCompletedBy()); - assertFalse(dispositionService.isNextDispositionActionEligible(recordFolder)); - - checkLastDispositionAction(recordFolder, "transfer", 2); - - return null; - } - }); - } - - private void checkSearchAspect(NodeRef record) - { - checkSearchAspect(record, true); - } - - private void checkSearchAspect(NodeRef record, boolean isPeriodSet) - { - DispositionAction da = dispositionService.getNextDispositionAction(record); - if (da != null) - { - assertTrue(nodeService.hasAspect(record, RecordsManagementSearchBehaviour.ASPECT_RM_SEARCH)); - assertEquals(da.getName(), - nodeService.getProperty(record, RecordsManagementSearchBehaviour.PROP_RS_DISPOSITION_ACTION_NAME)); - assertEquals(da.getAsOfDate(), - nodeService.getProperty(record, RecordsManagementSearchBehaviour.PROP_RS_DISPOSITION_ACTION_AS_OF)); - assertEquals(nodeService.getProperty(da.getNodeRef(), PROP_DISPOSITION_EVENTS_ELIGIBLE), - nodeService.getProperty(record, RecordsManagementSearchBehaviour.PROP_RS_DISPOSITION_EVENTS_ELIGIBLE)); - - int eventCount = da.getEventCompletionDetails().size(); - Collection events = (Collection)nodeService.getProperty(record, RecordsManagementSearchBehaviour.PROP_RS_DISPOSITION_EVENTS); - if (eventCount == 0) - { - assertNull(events); - } - else - { - assertEquals(eventCount, events.size()); - } - - DispositionActionDefinition daDef = da.getDispositionActionDefinition(); - assertNotNull(daDef); - Period period = daDef.getPeriod(); - if (isPeriodSet) - { - assertNotNull(period); - assertEquals(period.getPeriodType(), nodeService.getProperty(record, RecordsManagementSearchBehaviour.PROP_RS_DISPOSITION_PERIOD)); - assertEquals(period.getExpression(), nodeService.getProperty(record, RecordsManagementSearchBehaviour.PROP_RS_DISPOSITION_PERIOD_EXPRESSION)); - } - else - { - assertNull(period); - assertNull(nodeService.getProperty(record, RecordsManagementSearchBehaviour.PROP_RS_DISPOSITION_PERIOD)); - assertNull(nodeService.getProperty(record, RecordsManagementSearchBehaviour.PROP_RS_DISPOSITION_PERIOD_EXPRESSION)); - } - } - - DispositionSchedule ds = dispositionService.getDispositionSchedule(record); - Boolean value = (Boolean)nodeService.getProperty(record, RecordsManagementSearchBehaviour.PROP_RS_HAS_DISPOITION_SCHEDULE); - String dsInstructions = (String)nodeService.getProperty(record, RecordsManagementSearchBehaviour.PROP_RS_DISPOITION_INSTRUCTIONS); - String dsAuthority = (String)nodeService.getProperty(record, RecordsManagementSearchBehaviour.PROP_RS_DISPOITION_AUTHORITY); - if (ds != null) - { - assertTrue(value); - assertEquals(ds.getDispositionInstructions(), dsInstructions); - assertEquals(ds.getDispositionAuthority(), dsAuthority); - } - else - { - assertFalse(value); - } - - VitalRecordDefinition vrd = vitalRecordService.getVitalRecordDefinition(record); - if (vrd == null) - { - assertNull(nodeService.getProperty(record, RecordsManagementSearchBehaviour.PROP_RS_VITAL_RECORD_REVIEW_PERIOD)); - assertNull(nodeService.getProperty(record, RecordsManagementSearchBehaviour.PROP_RS_VITAL_RECORD_REVIEW_PERIOD_EXPRESSION)); - } - else - { - assertEquals(vrd.getReviewPeriod().getPeriodType(), - nodeService.getProperty(record, RecordsManagementSearchBehaviour.PROP_RS_VITAL_RECORD_REVIEW_PERIOD)); - assertEquals(vrd.getReviewPeriod().getExpression(), - nodeService.getProperty(record, RecordsManagementSearchBehaviour.PROP_RS_VITAL_RECORD_REVIEW_PERIOD_EXPRESSION)); - } - } - - - public void testDispositionLifecycle_0430_01_recordleveldisposition() throws Exception - { - NodeRef recordCategory = TestUtilities.getRecordCategory(rmService, nodeService, "Civilian Files", "Employee Performance File System Records"); - assertNotNull(recordCategory); - assertEquals("Employee Performance File System Records", this.nodeService.getProperty(recordCategory, ContentModel.PROP_NAME)); - - NodeRef recordFolder = createRecordFolder(recordCategory, "My Record Folder"); - - setComplete(); - endTransaction(); - - UserTransaction txn = transactionService.getUserTransaction(false); - txn.begin(); - - NodeRef recordOne = createRecord(recordFolder, "one.txt"); - - txn.commit(); - txn = transactionService.getUserTransaction(false); - txn.begin(); - - TestUtilities.declareRecord(recordOne, unprotectedNodeService, rmActionService); - - // Check the disposition action - assertTrue(this.nodeService.hasAspect(recordOne, ASPECT_DISPOSITION_LIFECYCLE)); - assertFalse(this.nodeService.hasAspect(recordFolder, ASPECT_DISPOSITION_LIFECYCLE)); - - // Check the dispostion action - DispositionAction da = dispositionService.getNextDispositionAction(recordOne); - assertNotNull(da); - assertEquals("cutoff", da.getDispositionActionDefinition().getName()); - assertNull(da.getAsOfDate()); - assertFalse((Boolean)this.nodeService.getProperty(da.getNodeRef(), PROP_DISPOSITION_EVENTS_ELIGIBLE)); - assertEquals(true, da.getDispositionActionDefinition().eligibleOnFirstCompleteEvent()); - List events = da.getEventCompletionDetails(); - assertNotNull(events); - assertEquals(1, events.size()); - EventCompletionDetails event = events.get(0); - - Map params = new HashMap(3); - params.put(CompleteEventAction.PARAM_EVENT_NAME, event.getEventName()); - params.put(CompleteEventAction.PARAM_EVENT_COMPLETED_AT, new Date()); - params.put(CompleteEventAction.PARAM_EVENT_COMPLETED_BY, "roy"); - - this.rmActionService.executeRecordsManagementAction(recordOne, "completeEvent", params); - - txn.commit(); - txn = transactionService.getUserTransaction(false); - txn.begin(); - - assertTrue((Boolean)this.nodeService.getProperty(da.getNodeRef(), PROP_DISPOSITION_EVENTS_ELIGIBLE)); - - // Do the commit action - this.rmActionService.executeRecordsManagementAction(recordOne, "cutoff", null); - - txn.commit(); - txn = transactionService.getUserTransaction(false); - txn.begin(); - - // Check events are gone - da = dispositionService.getNextDispositionAction(recordOne); - - assertNotNull(da); - assertEquals("destroy", da.getDispositionActionDefinition().getName()); - assertNotNull(da.getAsOfDate()); - assertFalse((Boolean)this.nodeService.getProperty(da.getNodeRef(), PROP_DISPOSITION_EVENTS_ELIGIBLE)); - events = da.getEventCompletionDetails(); - assertNotNull(events); - assertEquals(0, events.size()); - - final Calendar calendar = Calendar.getInstance(); - calendar.set(Calendar.HOUR, 0); - calendar.set(Calendar.MINUTE, 0); - calendar.set(Calendar.SECOND, 0); - - // Clock the asOf date back to ensure eligibility for destruction - NodeRef ndNodeRef = nodeService.getChildAssocs(recordOne, ASSOC_NEXT_DISPOSITION_ACTION, RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - Date nowDate = calendar.getTime(); - assertFalse(nowDate.equals(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF))); - params.clear(); - params.put(EditDispositionActionAsOfDateAction.PARAM_AS_OF_DATE, nowDate); - rmActionService.executeRecordsManagementAction(recordOne, "editDispositionActionAsOfDate", params); - assertTrue(nowDate.equals(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF))); - - - assertNotNull(nodeService.getProperty(recordOne, ContentModel.PROP_CONTENT)); - - rmActionService.executeRecordsManagementAction(recordOne, "destroy", null); - - // Check that the node has been ghosted - assertTrue(nodeService.exists(recordOne)); - assertTrue(nodeService.hasAspect(recordOne, RecordsManagementModel.ASPECT_GHOSTED)); - assertNull(nodeService.getProperty(recordOne, ContentModel.PROP_CONTENT)); - - txn.commit(); - } - - public void testDispositionLifecycle_0412_03_eventtest() throws Exception - { - NodeRef recordCategory = TestUtilities.getRecordCategory(rmService, nodeService, "Military Files", "Personnel Security Program Records"); - assertNotNull(recordCategory); - assertEquals("Personnel Security Program Records", this.nodeService.getProperty(recordCategory, ContentModel.PROP_NAME)); - - Map folderProps = new HashMap(1); - folderProps.put(ContentModel.PROP_NAME, "My Folder"); - NodeRef recordFolder = this.nodeService.createNode(recordCategory, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "My Folder"), - TYPE_RECORD_FOLDER).getChildRef(); - setComplete(); - endTransaction(); - - UserTransaction txn = transactionService.getUserTransaction(false); - txn.begin(); - - NodeRef recordOne = createRecord(recordFolder); - - txn.commit(); - txn = transactionService.getUserTransaction(false); - txn.begin(); - - TestUtilities.declareRecord(recordOne, unprotectedNodeService, rmActionService); - - // NOTE the disposition is being managed at a folder level ... - - // Check the disposition action - assertFalse(this.nodeService.hasAspect(recordOne, ASPECT_DISPOSITION_LIFECYCLE)); - assertTrue(this.nodeService.hasAspect(recordFolder, ASPECT_DISPOSITION_LIFECYCLE)); - - // Check the dispostion action - DispositionAction da = dispositionService.getNextDispositionAction(recordFolder); - assertNotNull(da); - assertEquals("cutoff", da.getDispositionActionDefinition().getName()); - assertNull(da.getAsOfDate()); - assertFalse((Boolean)this.nodeService.getProperty(da.getNodeRef(), PROP_DISPOSITION_EVENTS_ELIGIBLE)); - assertEquals(false, da.getDispositionActionDefinition().eligibleOnFirstCompleteEvent()); - List events = da.getEventCompletionDetails(); - assertNotNull(events); - assertEquals(3, events.size()); - - checkSearchAspect(recordFolder); - - txn.commit(); - txn = transactionService.getUserTransaction(false); - txn.begin(); - - EventCompletionDetails ecd = events.get(0); - assertFalse(ecd.isEventComplete()); - assertNull(ecd.getEventCompletedBy()); - assertNull(ecd.getEventCompletedAt()); - - Map params = new HashMap(3); - params.put(CompleteEventAction.PARAM_EVENT_NAME, events.get(0).getEventName()); - params.put(CompleteEventAction.PARAM_EVENT_COMPLETED_AT, new Date()); - params.put(CompleteEventAction.PARAM_EVENT_COMPLETED_BY, "roy"); - - checkSearchAspect(recordFolder); - - this.rmActionService.executeRecordsManagementAction(recordFolder, "completeEvent", params); - - txn.commit(); - txn = transactionService.getUserTransaction(false); - txn.begin(); - - assertFalse((Boolean)this.nodeService.getProperty(da.getNodeRef(), PROP_DISPOSITION_EVENTS_ELIGIBLE)); - assertEquals(false, da.getDispositionActionDefinition().eligibleOnFirstCompleteEvent()); - events = da.getEventCompletionDetails(); - assertNotNull(events); - assertEquals(3, events.size()); - - params = new HashMap(3); - params.put(CompleteEventAction.PARAM_EVENT_NAME, events.get(1).getEventName()); - params.put(CompleteEventAction.PARAM_EVENT_COMPLETED_AT, new Date()); - params.put(CompleteEventAction.PARAM_EVENT_COMPLETED_BY, "roy"); - - checkSearchAspect(recordFolder); - - this.rmActionService.executeRecordsManagementAction(recordFolder, "completeEvent", params); - - txn.commit(); - txn = transactionService.getUserTransaction(false); - txn.begin(); - - assertFalse((Boolean)this.nodeService.getProperty(da.getNodeRef(), PROP_DISPOSITION_EVENTS_ELIGIBLE)); - - params = new HashMap(3); - params.put(CompleteEventAction.PARAM_EVENT_NAME, events.get(2).getEventName()); - params.put(CompleteEventAction.PARAM_EVENT_COMPLETED_AT, new Date()); - params.put(CompleteEventAction.PARAM_EVENT_COMPLETED_BY, "roy"); - - checkSearchAspect(recordFolder); - - this.rmActionService.executeRecordsManagementAction(recordFolder, "completeEvent", params); - - txn.commit(); - txn = transactionService.getUserTransaction(false); - txn.begin(); - - assertTrue((Boolean)this.nodeService.getProperty(da.getNodeRef(), PROP_DISPOSITION_EVENTS_ELIGIBLE)); - - events = da.getEventCompletionDetails(); - assertNotNull(events); - assertEquals(3, events.size()); - for (EventCompletionDetails e : events) - { - assertTrue(e.isEventComplete()); - assertEquals("roy", e.getEventCompletedBy()); - assertNotNull(e.getEventCompletedAt()); - } - - checkSearchAspect(recordFolder); - - // Test undo - - params = new HashMap(1); - params.put(CompleteEventAction.PARAM_EVENT_NAME, events.get(2).getEventName()); - this.rmActionService.executeRecordsManagementAction(recordFolder, "undoEvent", params); - - txn.commit(); - txn = transactionService.getUserTransaction(false); - txn.begin(); - - assertFalse((Boolean)this.nodeService.getProperty(da.getNodeRef(), PROP_DISPOSITION_EVENTS_ELIGIBLE)); - - params = new HashMap(3); - params.put(CompleteEventAction.PARAM_EVENT_NAME, events.get(2).getEventName()); - params.put(CompleteEventAction.PARAM_EVENT_COMPLETED_AT, new Date()); - params.put(CompleteEventAction.PARAM_EVENT_COMPLETED_BY, "roy"); - - this.rmActionService.executeRecordsManagementAction(recordFolder, "completeEvent", params); - - txn.commit(); - txn = transactionService.getUserTransaction(false); - txn.begin(); - - assertTrue((Boolean)this.nodeService.getProperty(da.getNodeRef(), PROP_DISPOSITION_EVENTS_ELIGIBLE)); - - // Do the commit action - this.rmActionService.executeRecordsManagementAction(recordFolder, "cutoff", null); - - txn.commit(); - txn = transactionService.getUserTransaction(false); - txn.begin(); - - // Check events are gone - da = dispositionService.getNextDispositionAction(recordFolder); - - assertNotNull(da); - assertEquals("destroy", da.getDispositionActionDefinition().getName()); - assertNotNull(da.getAsOfDate()); - assertFalse((Boolean)this.nodeService.getProperty(da.getNodeRef(), PROP_DISPOSITION_EVENTS_ELIGIBLE)); - events = da.getEventCompletionDetails(); - assertNotNull(events); - assertEquals(0, events.size()); - - checkSearchAspect(recordFolder); - - txn.commit(); - } - - private NodeRef createRecord(NodeRef recordFolder) - { - return createRecord(recordFolder, "MyRecord.txt"); - } - - private NodeRef createRecord(NodeRef recordFolder, String name) - { - return createRecord(recordFolder, name, "There is some content in this record"); - } - - private NodeRef createRecord(NodeRef recordFolder, String name, String someTextContent) - { - // Create the document - Map props = new HashMap(1); - props.put(ContentModel.PROP_NAME, name); - NodeRef recordOne = this.nodeService.createNode(recordFolder, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, name), - ContentModel.TYPE_CONTENT, - props).getChildRef(); - - // Set the content - ContentWriter writer = this.contentService.getWriter(recordOne, ContentModel.PROP_CONTENT, true); - writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); - writer.setEncoding("UTF-8"); - writer.putContent(someTextContent); - - return recordOne; - } - - /** - * This method tests the filing of a custom type, as defined in DOD 5015. - */ - public void testFileDOD5015CustomTypes() throws Exception - { - NodeRef recordCategory = TestUtilities.getRecordCategory(rmService, nodeService, "Reports", "AIS Audit Records"); - - NodeRef recordFolder = createRecordFolder(recordCategory, "March AIS Audit Records"); - setComplete(); - endTransaction(); - - UserTransaction txn = transactionService.getUserTransaction(false); - txn.begin(); - - NodeRef testDocument = this.nodeService.createNode(recordFolder, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "CustomType"), - ContentModel.TYPE_CONTENT).getChildRef(); - - // It's not necessary to set content for this test. - - // File the record. - rmActionService.executeRecordsManagementAction(testDocument, "file"); - - assertTrue("testDocument should be a record.", rmService.isRecord(testDocument)); - - // Have the customType aspect applied.. - Map props = new HashMap(); - props.put(PROP_SCANNED_FORMAT.toPrefixString(serviceRegistry.getNamespaceService()), "f"); - props.put(PROP_SCANNED_FORMAT_VERSION.toPrefixString(serviceRegistry.getNamespaceService()), "1.0"); - props.put(PROP_RESOLUTION_X.toPrefixString(serviceRegistry.getNamespaceService()), "100"); - props.put(PROP_RESOLUTION_Y.toPrefixString(serviceRegistry.getNamespaceService()), "100"); - props.put(PROP_SCANNED_BIT_DEPTH.toPrefixString(serviceRegistry.getNamespaceService()), "10"); - rmActionService.executeRecordsManagementAction(testDocument, "applyScannedRecord", props); - - assertTrue("Custom type should have ScannedRecord aspect.", nodeService.hasAspect(testDocument, DOD5015Model.ASPECT_SCANNED_RECORD)); - - txn.rollback(); - } - - public void testFileDOD5015CustomTypes2() throws Exception - { - NodeRef recordCategory = TestUtilities.getRecordCategory(rmService, nodeService, "Reports", "AIS Audit Records"); - - NodeRef recordFolder = createRecordFolder(recordCategory, "March AIS Audit Records"); - setComplete(); - endTransaction(); - - UserTransaction txn = transactionService.getUserTransaction(false); - txn.begin(); - - NodeRef testDocument = this.nodeService.createNode(recordFolder, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "CustomType"), - ContentModel.TYPE_CONTENT).getChildRef(); - - // It's not necessary to set content for this test. - - // File the record - List aspects = new ArrayList(1); - aspects.add(DOD5015Model.ASPECT_SCANNED_RECORD); - Map props = new HashMap(1); - props.put(FileAction.PARAM_RECORD_METADATA_ASPECTS, (Serializable)aspects); - rmActionService.executeRecordsManagementAction(testDocument, "file", props); - - assertTrue("testDocument should be a record.", rmService.isRecord(testDocument)); - assertTrue("Custom type should have ScannedRecord aspect.", nodeService.hasAspect(testDocument, DOD5015Model.ASPECT_SCANNED_RECORD)); - - txn.rollback(); - } - - /** - * This method tests the filing of an already existing document i.e. one that is - * already contained within the document library. - */ - public void testFileFromDoclib() throws Exception - { - // Get the relevant RecordCategory and create a RecordFolder underneath it. - NodeRef recordCategory = TestUtilities.getRecordCategory(rmService, nodeService, "Reports", "AIS Audit Records"); - - NodeRef recordFolder = createRecordFolder(recordCategory, "March AIS Audit Records"); - setComplete(); - endTransaction(); - - UserTransaction txn = transactionService.getUserTransaction(false); - txn.begin(); - - // Unlike testBasicFilingTest, we now create a normal Alfresco content node - // rather than a fully-fledged record. The content must also be outside the - // fileplan. - - // Create a site - to put the content in. - final String rmTestSiteShortName = "rmTest" + System.currentTimeMillis(); - this.serviceRegistry.getSiteService().createSite("RMTestSite", rmTestSiteShortName, - "Test site for Records Management", "", SiteVisibility.PUBLIC); - - NodeRef siteRoot = this.serviceRegistry.getSiteService().getSite(rmTestSiteShortName).getNodeRef(); - NodeRef siteDocLib = this.nodeService.createNode(siteRoot, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "documentLibrary"), - ContentModel.TYPE_FOLDER).getChildRef(); - // Create the test document - NodeRef testDocument = this.nodeService.createNode(siteDocLib, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "PreexistingDocument.txt"), - ContentModel.TYPE_CONTENT).getChildRef(); - // Set some content - ContentWriter writer = this.contentService.getWriter(testDocument, ContentModel.PROP_CONTENT, true); - writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); - writer.setEncoding("UTF-8"); - writer.putContent("Some dummy content."); - - txn.commit(); - txn = transactionService.getUserTransaction(false); - txn.begin(); - - // Clearly, this should not be a record at this point. - assertFalse(this.nodeService.hasAspect(testDocument, ASPECT_RECORD)); - - // Now we want to file this document as a record within the RMA. - // To do this we simply move a document into the fileplan and file - this.serviceRegistry.getFileFolderService().move(testDocument, recordFolder, null); - rmActionService.executeRecordsManagementAction(testDocument, "file"); - - assertTrue("testDocument should be a record.", rmService.isRecord(testDocument)); - assertNotNull(this.nodeService.getProperty(testDocument, PROP_IDENTIFIER)); - assertNotNull(this.nodeService.getProperty(testDocument, PROP_DATE_FILED)); - - // Check the review schedule - assertTrue(this.nodeService.hasAspect(testDocument, ASPECT_VITAL_RECORD)); - assertNotNull(this.nodeService.getProperty(testDocument, PROP_REVIEW_AS_OF)); - - txn.commit(); - } - - /** - * This method tests the filing of non-electronic record. - */ - public void testFileNonElectronicRecord() throws Exception - { - setComplete(); - endTransaction(); - - // Create a record folder - final NodeRef recordFolder = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - // Get the relevant RecordCategory and create a RecordFolder underneath it. - NodeRef recordCategory = TestUtilities.getRecordCategory(rmService, nodeService, "Reports", "AIS Audit Records"); - NodeRef result = createRecordFolder(recordCategory, "March AIS Audit Records" + System.currentTimeMillis()); - - return result; - } - }); - - // Create a non-electronic record - final NodeRef nonElectronicTestRecord = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - // Create the document - NodeRef result = nodeService.createNode(recordFolder, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "Non-electronic Record" + System.currentTimeMillis()), - RecordsManagementModel.TYPE_NON_ELECTRONIC_DOCUMENT).getChildRef(); - - // There is no content on a non-electronic record. - - // These properties are required in order to declare the record. - Map props = nodeService.getProperties(result); - props.put(RecordsManagementModel.PROP_ORIGINATING_ORGANIZATION, "alfresco"); - props.put(RecordsManagementModel.PROP_ORIGINATOR, "admin"); - props.put(RecordsManagementModel.PROP_PUBLICATION_DATE, new Date()); - - Calendar fileCalendar = Calendar.getInstance(); - String year = Integer.toString(fileCalendar.get(Calendar.YEAR)); - props.put(RecordsManagementModel.PROP_DATE_FILED, fileCalendar.getTime()); - - String recordId = year + "-" + nodeService.getProperty(result, ContentModel.PROP_NODE_DBID).toString(); - props.put(RecordsManagementModel.PROP_IDENTIFIER, recordId); - - - nodeService.setProperties(result, props); - - return result; - } - }); - - // File and declare the record - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - assertTrue("Expected non-electronic record to be a record.", rmService.isRecord(nonElectronicTestRecord)); - assertFalse("Expected non-electronic record not to be declared yet.", rmService.isRecordDeclared(nonElectronicTestRecord)); - - rmActionService.executeRecordsManagementAction(nonElectronicTestRecord, "declareRecord"); - - assertTrue("Non-electronic record should now be declared.", rmService.isRecordDeclared(nonElectronicTestRecord)); - - // These properties are added automatically when the record is filed - assertNotNull(nodeService.getProperty(nonElectronicTestRecord, RecordsManagementModel.PROP_IDENTIFIER)); - assertNotNull(nodeService.getProperty(nonElectronicTestRecord, RecordsManagementModel.PROP_DATE_FILED)); - -// assertNotNull(nodeService.getProperty(testRecord, ContentModel.PROP_TITLE)); -// assertNotNull(nodeService.getProperty(testRecord, RecordsManagementModel.PROP_SUPPLEMENTAL_MARKING_LIST)); -// assertNotNull(nodeService.getProperty(testRecord, RecordsManagementModel.PROP_MEDIA_TYPE)); -// assertNotNull(nodeService.getProperty(testRecord, RecordsManagementModel.PROP_FORMAT)); -// assertNotNull(nodeService.getProperty(testRecord, RecordsManagementModel.PROP_DATE_RECEIVED)); -// assertEquals("foo", nodeService.getProperty(testRecord, RecordsManagementModel.PROP_ADDRESS)); -// assertEquals("foo", nodeService.getProperty(testRecord, RecordsManagementModel.PROP_OTHER_ADDRESS)); -// assertNotNull(nodeService.getProperty(testRecord, RecordsManagementModel.PROP_LOCATION)); -// assertEquals("foo", nodeService.getProperty(testRecord, RecordsManagementModel.PROP_PROJECT_NAME)); - - //TODO Add links to other records as per test doc. - return null; - } - }); - } - - private NodeRef createRecordFolder(NodeRef recordCategory, String folderName) - { - Map folderProps = new HashMap(1); - folderProps.put(ContentModel.PROP_NAME, folderName); - NodeRef recordFolder = this.nodeService.createNode(recordCategory, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, folderName), - TYPE_RECORD_FOLDER).getChildRef(); - return recordFolder; - } - - /** - * Caveat Config - * - * @throws Exception - */ - public void testCaveatConfig() throws Exception - { - setComplete(); - endTransaction(); - - cleanCaveatConfigData(); - setupCaveatConfigData(); - - // set/reset allowed values (empty list by default) - - final List newValues = new ArrayList(4); - newValues.add(NOFORN); - newValues.add(NOCONTRACT); - newValues.add(FOUO); - newValues.add(FGI); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - rmAdminService.changeCustomConstraintValues(RecordsManagementCustomModel.CONSTRAINT_CUSTOM_SMLIST, newValues); - - return null; - } - }); - - final NodeRef recordFolder = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - // Test list of allowed values for caveats - - List allowedValues = AuthenticationUtil.runAs(new RunAsWork>() - { - public List doWork() - { - // get allowed values for given caveat (for current user) - return caveatConfigService.getRMAllowedValues("rmc:smList"); - } - }, "dfranco"); - - assertEquals(2, allowedValues.size()); - assertTrue(allowedValues.contains(NOFORN)); - assertTrue(allowedValues.contains(FOUO)); - - - allowedValues = AuthenticationUtil.runAs(new RunAsWork>() - { - public List doWork() - { - // get allowed values for given caveat (for current user) - return caveatConfigService.getRMAllowedValues("rmc:smList"); - } - }, "dmartinz"); - - assertEquals(4, allowedValues.size()); - assertTrue(allowedValues.contains(NOFORN)); - assertTrue(allowedValues.contains(NOCONTRACT)); - assertTrue(allowedValues.contains(FOUO)); - assertTrue(allowedValues.contains(FGI)); - - - // Create record category / record folder - - final NodeRef recordCategory = TestUtilities.getRecordCategory(rmService, nodeService, "Reports", "AIS Audit Records"); - assertNotNull(recordCategory); - assertEquals("AIS Audit Records", nodeService.getProperty(recordCategory, ContentModel.PROP_NAME)); - - NodeRef recordFolder = createRecordFolder(recordCategory, "March AIS Audit Records"); - assertNotNull(recordFolder); - assertEquals(TYPE_RECORD_FOLDER, nodeService.getType(recordFolder)); - - // set RM capabilities on the file plan - to view & read records - setPermission(filePlan, PermissionService.ALL_AUTHORITIES, RMPermissionModel.VIEW_RECORDS, true); - setPermission(filePlan, PermissionService.ALL_AUTHORITIES, RMPermissionModel.READ_RECORDS, true); - - // set RM capabilities on the record folder - to read records - setPermission(recordFolder, PermissionService.ALL_AUTHORITIES, RMPermissionModel.READ_RECORDS, true); - - - return recordFolder; - } - }); - - final String RECORD_NAME = "MyRecord"+System.currentTimeMillis()+".txt"; - final String SOME_CONTENT = "There is some content in this record"; - - final NodeRef recordOne = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - int expectedChildCount = nodeService.getChildAssocs(recordFolder).size(); - - NodeRef recordOne = createRecord(recordFolder, RECORD_NAME, SOME_CONTENT); - - assertEquals(expectedChildCount+1, nodeService.getChildAssocs(recordFolder).size()); - - return recordOne; - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - assertTrue(nodeService.hasAspect(recordOne, ASPECT_RECORD)); - - int expectedChildCount = nodeService.getChildAssocs(recordFolder).size()-1; - - // - // Test caveats (security interceptors) BEFORE setting properties - // - - sanityCheckAccess("dmartinz", recordFolder, recordOne, RECORD_NAME, SOME_CONTENT, true, expectedChildCount); - sanityCheckAccess("gsmith", recordFolder, recordOne, RECORD_NAME, SOME_CONTENT, true, expectedChildCount); - sanityCheckAccess("dsandy", recordFolder, recordOne, RECORD_NAME, SOME_CONTENT, true, expectedChildCount); - - // Test setting properties (with restricted set of allowed values) - - // Set supplemental markings list (on record) - // TODO - set supplemental markings list (on record folder) - - AuthenticationUtil.runAs(new RunAsWork() - { - public Object doWork() - { - // set RM capabilities on the file plan - to file records and add/edit properties (ie. edit record) - setPermission(filePlan, "dfranco", RMPermissionModel.FILING, true); - setPermission(filePlan, "dfranco", RMPermissionModel.EDIT_RECORD_METADATA, true); - return null; - } - }, "admin"); - - - AuthenticationUtil.setFullyAuthenticatedUser("dfranco"); - assertEquals(AccessStatus.ALLOWED, publicServiceAccessService.hasAccess("NodeService", "exists", recordFolder)); - - return null; - } - }); - - try - { - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - - // Set smList - - Map propValues = new HashMap(1); - List smList = new ArrayList(3); - smList.add(FOUO); - smList.add(NOFORN); - smList.add(NOCONTRACT); - propValues.put(RecordsManagementModel.PROP_SUPPLEMENTAL_MARKING_LIST, (Serializable)smList); - nodeService.addProperties(recordOne, propValues); - - return null; - } - }); - - fail("Should fail with integrity exception"); // user 'dfranco' not allowed 'NOCONTRACT' - } - catch (IntegrityException ie) - { - // expected - } - - try - { - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // Set smList - - Map propValues = new HashMap(1); - List smList = new ArrayList(2); - smList.add(FOUO); - smList.add(NOFORN); - propValues.put(RecordsManagementModel.PROP_SUPPLEMENTAL_MARKING_LIST, (Serializable)smList); - nodeService.addProperties(recordOne, propValues); - - return null; - } - }); - } - catch (IntegrityException ie) - { - fail(""+ie); - } - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - @SuppressWarnings("unchecked") - List smList = (List)nodeService.getProperty(recordOne, RecordsManagementModel.PROP_SUPPLEMENTAL_MARKING_LIST); - assertEquals(2, smList.size()); - assertTrue(smList.contains(NOFORN)); - assertTrue(smList.contains(FOUO)); - - return null; - } - }); - - // User-defined field (in this case, "rmc:prjList" on record) - - // Create custom constraint (or reset values if it already exists) - - // create new custom constraint - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - try - { - List emptyList = new ArrayList(0); - rmAdminService.addCustomConstraintDefinition(CONSTRAINT_CUSTOM_PRJLIST, "Some Projects", true, emptyList, MatchLogic.AND); - } - catch (AlfrescoRuntimeException e) - { - // ignore - ie. assume exception is due to the fact that it already exists - } - - return null; - } - }); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - List newerValues = new ArrayList(3); - newerValues.add(PRJ_A); - newerValues.add(PRJ_B); - newerValues.add(PRJ_C); - - rmAdminService.changeCustomConstraintValues(CONSTRAINT_CUSTOM_PRJLIST, newerValues); - - return null; - } - }); - - // define custom property and reference custom constraint - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - try - { - // Define a custom "project list" property (for records) - note: multi-valued - rmAdminService.addCustomPropertyDefinition( - PROP_CUSTOM_PRJLIST, - ASPECT_RECORD, - PROP_CUSTOM_PRJLIST.getLocalName(), - DataTypeDefinition.TEXT, "Projects", - null, - null, - true, - false, - false, - CONSTRAINT_CUSTOM_PRJLIST); - } - catch (AlfrescoRuntimeException e) - { - // ignore - ie. assume exception is due to the fact that it already exists - } - - return null; - } - }); - - try - { - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - - // Set prjList - - Map propValues = new HashMap(1); - List prjList = new ArrayList(3); - prjList.add(PRJ_A); - prjList.add(PRJ_B); - propValues.put(PROP_CUSTOM_PRJLIST, (Serializable)prjList); - nodeService.addProperties(recordOne, propValues); - - return null; - } - }); - - fail("Should fail with integrity exception"); // user 'dfranco' not allowed 'Project B' - } - catch (IntegrityException ie) - { - // expected - } - - try - { - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // Set prjList - Map propValues = new HashMap(1); - List prjList = new ArrayList(3); - prjList.add(PRJ_A); - propValues.put(PROP_CUSTOM_PRJLIST, (Serializable)prjList); - nodeService.addProperties(recordOne, propValues); - - return null; - } - }); - } - catch (IntegrityException ie) - { - fail(""+ie); - } - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - @SuppressWarnings("unchecked") - List prjList = (List)nodeService.getProperty(recordOne, PROP_CUSTOM_PRJLIST); - assertEquals(1, prjList.size()); - assertTrue(prjList.contains(PRJ_A)); - - return null; - } - }); - - // - // Test caveats (security interceptors) AFTER setting properties - // - - int expectedChildCount = nodeService.getChildAssocs(recordFolder).size()-1; - sanityCheckAccess("dmartinz", recordFolder, recordOne, RECORD_NAME, SOME_CONTENT, true, expectedChildCount); - sanityCheckAccess("gsmith", recordFolder, recordOne, RECORD_NAME, SOME_CONTENT, false, expectedChildCount); // denied by rma:prjList ("Project A") - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); - addToGroup("gsmith", "Engineering"); - - return null; - } - }); - - sanityCheckAccess("gsmith", recordFolder, recordOne, RECORD_NAME, SOME_CONTENT, true, expectedChildCount); - sanityCheckAccess("dsandy", recordFolder, recordOne, RECORD_NAME, SOME_CONTENT, false, expectedChildCount); // denied by rma:smList ("NOFORN", "FOUO") - - cleanCaveatConfigData(); - } - - private void setPermission(NodeRef nodeRef, String authority, String permission, boolean allow) - { - permissionService.setPermission(nodeRef, authority, permission, allow); - if (permission.equals(RMPermissionModel.FILING)) - { - if (rmService.isRecordCategory(nodeRef) == true) - { - List assocs = nodeService.getChildAssocs(nodeRef, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL); - for (ChildAssociationRef assoc : assocs) - { - NodeRef child = assoc.getChildRef(); - if (rmService.isRecordFolder(child) == true || rmService.isRecordCategory(child) == true) - { - setPermission(child, authority, permission, allow); - } - } - } - } - } - - private void cleanCaveatConfigData() - { - startNewTransaction(); - - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); - - deleteUser("jrangel"); - deleteUser("dmartinz"); - deleteUser("jrogers"); - deleteUser("hmcneil"); - deleteUser("dfranco"); - deleteUser("gsmith"); - deleteUser("eharris"); - deleteUser("bbayless"); - deleteUser("mhouse"); - deleteUser("aly"); - deleteUser("dsandy"); - deleteUser("driggs"); - deleteUser("test1"); - - deleteGroup("Engineering"); - deleteGroup("Finance"); - deleteGroup("test1"); - - caveatConfigService.updateOrCreateCaveatConfig("{}"); // empty config ! - - setComplete(); - endTransaction(); - } - - private void setupCaveatConfigData() - { - startNewTransaction(); - - // Switch to admin - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); - - // Create test users/groups (if they do not already exist) - - createUser("jrangel"); - createUser("dmartinz"); - createUser("jrogers"); - createUser("hmcneil"); - createUser("dfranco"); - createUser("gsmith"); - createUser("eharris"); - createUser("bbayless"); - createUser("mhouse"); - createUser("aly"); - createUser("dsandy"); - createUser("driggs"); - createUser("test1"); - - createGroup("Engineering"); - createGroup("Finance"); - createGroup("test1"); - - addToGroup("jrogers", "Engineering"); - addToGroup("dfranco", "Finance"); - - // not in grouo to start with - added later - //addToGroup("gsmith", "Engineering"); - - File file = new File(System.getProperty("user.dir")+"/test-resources/testCaveatConfig2.json"); // from test-resources - assertTrue(file.exists()); - - caveatConfigService.updateOrCreateCaveatConfig(file); - - setComplete(); - endTransaction(); - } - - protected void createUser(String userName) - { - if (! authenticationService.authenticationExists(userName)) - { - authenticationService.createAuthentication(userName, "PWD".toCharArray()); - } - - if (! personService.personExists(userName)) - { - PropertyMap ppOne = new PropertyMap(4); - ppOne.put(ContentModel.PROP_USERNAME, userName); - ppOne.put(ContentModel.PROP_FIRSTNAME, "firstName"); - ppOne.put(ContentModel.PROP_LASTNAME, "lastName"); - ppOne.put(ContentModel.PROP_EMAIL, "email@email.com"); - ppOne.put(ContentModel.PROP_JOBTITLE, "jobTitle"); - - personService.createPerson(ppOne); - } - } - - protected void deleteUser(String userName) - { - if (personService.personExists(userName)) - { - personService.deletePerson(userName); - } - } - - protected void createGroup(String groupShortName) - { - createGroup(null, groupShortName); - } - - protected void createGroup(String parentGroupShortName, String groupShortName) - { - if (parentGroupShortName != null) - { - String parentGroupFullName = authorityService.getName(AuthorityType.GROUP, parentGroupShortName); - if (authorityService.authorityExists(parentGroupFullName) == false) - { - authorityService.createAuthority(AuthorityType.GROUP, groupShortName, groupShortName, null); - authorityService.addAuthority(parentGroupFullName, groupShortName); - } - } - else - { - authorityService.createAuthority(AuthorityType.GROUP, groupShortName, groupShortName, null); - } - } - - protected void deleteGroup(String groupShortName) - { - String groupFullName = authorityService.getName(AuthorityType.GROUP, groupShortName); - if (authorityService.authorityExists(groupFullName) == true) - { - authorityService.deleteAuthority(groupFullName); - } - } - - protected void addToGroup(String authorityName, String groupShortName) - { - authorityService.addAuthority(authorityService.getName(AuthorityType.GROUP, groupShortName), authorityName); - } - - protected void removeFromGroup(String authorityName, String groupShortName) - { - authorityService.removeAuthority(authorityService.getName(AuthorityType.GROUP, groupShortName), authorityName); - } - - private void sanityCheckAccess(String user, NodeRef recordFolder, NodeRef record, String expectedName, String expectedContent, boolean expectedAllowed, int baseCount) - { - //startNewTransaction(); - - AuthenticationUtil.setFullyAuthenticatedUser(user); - - // Sanity check search service - eg. query - - String query = "ID:"+AbstractLuceneQueryParser.escape(record.toString()); - ResultSet rs = this.searchService.query(SPACES_STORE, SearchService.LANGUAGE_LUCENE, query); - - if (expectedAllowed) - { - assertEquals(1, rs.length()); - assertEquals(record.toString(), rs.getNodeRef(0).toString()); - } - else - { - assertEquals(0, rs.length()); - } - rs.close(); - - // Sanity check node service - eg. getProperty, getChildAssocs - - try - { - Serializable value = this.nodeService.getProperty(record, ContentModel.PROP_NAME); - - if (expectedAllowed) - { - assertNotNull(value); - assertEquals(expectedName, (String)value); - } - else - { - fail("Unexpected - access should be denied by caveats"); - } - } - catch (AccessDeniedException ade) - { - if (expectedAllowed) - { - fail("Unexpected - access should be allowed by caveats"); - } - - // expected - } - - List childAssocs = nodeService.getChildAssocs(recordFolder); - - if (expectedAllowed) - { - assertEquals(baseCount+1, childAssocs.size()); - assertEquals(record.toString(), childAssocs.get(baseCount).getChildRef().toString()); - } - else - { - assertEquals(baseCount, childAssocs.size()); - } - - // Sanity check content service - eg. getReader - - try - { - ContentReader reader = this.contentService.getReader(record, ContentModel.PROP_CONTENT); - - if (expectedAllowed) - { - assertNotNull(reader); - assertEquals(expectedContent, reader.getContentString()); - } - else - { - fail("Unexpected - access should be denied by caveats"); - } - } - catch (AccessDeniedException ade) - { - if (expectedAllowed) - { - fail("Unexpected - access should be allowed by caveats"); - } - - // expected - } - - //setComplete(); - //endTransaction(); - } - - /** - * https://issues.alfresco.com/jira/browse/ETHREEOH-3587 - */ - public void testETHREEOH3587() - { - NodeRef recordFolder = TestUtilities.getRecordFolder(rmService, nodeService, "Reports", "AIS Audit Records", "January AIS Audit Records"); - assertNotNull(recordFolder); - - // Create a record - final NodeRef record = createRecord(recordFolder, GUID.generate()); - - // Commit in order to trigger the setUpRecordFolder behaviour - setComplete(); - endTransaction(); - - // Now try and update the id, this should fail - try - { - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // Lets just check the record identifier has been set - String id = (String)nodeService.getProperty(record, RecordsManagementModel.PROP_IDENTIFIER); - assertNotNull(id); - - nodeService.setProperty(record, RecordsManagementModel.PROP_IDENTIFIER, "randomValue"); - - return null; - } - }); - - fail("You should not be allowed to update the identifier of a record once it has been created."); - } - catch(AlfrescoRuntimeException e) - { - // Expected - } - - // TODO set the identifier of the second record to be the same as the first .... - } - - /** - * Vital Record Test - * - * @throws Exception - */ - public void testVitalRecords() throws Exception - { - // - // Create a record folder under a "vital" category - // - - // TODO Don't think I need to do this. Can I reuse the existing January one? - - NodeRef vitalRecCategory = - TestUtilities.getRecordCategory(rmService, nodeService, "Reports", "AIS Audit Records"); - - assertNotNull(vitalRecCategory); - assertEquals("AIS Audit Records", - this.nodeService.getProperty(vitalRecCategory, ContentModel.PROP_NAME)); - - NodeRef vitalRecFolder = this.nodeService.createNode(vitalRecCategory, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, - "March AIS Audit Records"), - TYPE_RECORD_FOLDER).getChildRef(); - setComplete(); - endTransaction(); - UserTransaction txn1 = transactionService.getUserTransaction(false); - txn1.begin(); - - // Check the Vital Record data - VitalRecordDefinition vitalRecCatDefinition = vitalRecordService.getVitalRecordDefinition(vitalRecCategory); - assertNotNull("This record category should have a VitalRecordDefinition", vitalRecCatDefinition); - assertTrue(vitalRecCatDefinition.isEnabled()); - - VitalRecordDefinition vitalRecFolderDefinition = vitalRecordService.getVitalRecordDefinition(vitalRecFolder); - assertNotNull("This record folder should have a VitalRecordDefinition", vitalRecFolderDefinition); - assertTrue(vitalRecFolderDefinition.isEnabled()); - - assertEquals("The Vital Record reviewPeriod in the folder did not match its parent category", - vitalRecFolderDefinition.getReviewPeriod(), - vitalRecCatDefinition.getReviewPeriod()); - - // check the search aspect for both the category and folder - checkSearchAspect(vitalRecFolder); - - // Create a vital record - NodeRef vitalRecord = this.nodeService.createNode(vitalRecFolder, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, - "MyVitalRecord" + System.currentTimeMillis() +".txt"), - ContentModel.TYPE_CONTENT).getChildRef(); - - // Set the content - ContentWriter writer = this.contentService.getWriter(vitalRecord, ContentModel.PROP_CONTENT, true); - writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); - writer.setEncoding("UTF-8"); - writer.putContent("There is some content in this record"); - - rmActionService.executeRecordsManagementAction(vitalRecord, "file"); - - txn1.commit(); - - UserTransaction txn2 = transactionService.getUserTransaction(false); - txn2.begin(); - - // Check the review schedule - - assertTrue(this.nodeService.hasAspect(vitalRecord, ASPECT_VITAL_RECORD)); - VitalRecordDefinition vitalRecDefinition = vitalRecordService.getVitalRecordDefinition(vitalRecord); - assertTrue(vitalRecDefinition.isEnabled()); - Date vitalRecordAsOfDate = (Date)this.nodeService.getProperty(vitalRecord, PROP_REVIEW_AS_OF); - assertNotNull("vitalRecord should have a reviewAsOf date.", vitalRecordAsOfDate); - - // check the search aspect for the vital record - checkSearchAspect(vitalRecord); - - // - // Create a record folder under a "non-vital" category - // - NodeRef nonVitalRecordCategory = TestUtilities.getRecordCategory(rmService, nodeService, "Reports", "Unit Manning Documents"); - assertNotNull(nonVitalRecordCategory); - assertEquals("Unit Manning Documents", this.nodeService.getProperty(nonVitalRecordCategory, ContentModel.PROP_NAME)); - - NodeRef nonVitalFolder = this.nodeService.createNode(nonVitalRecordCategory, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "4th Quarter Unit Manning Documents"), - TYPE_RECORD_FOLDER).getChildRef(); - txn2.commit(); - - UserTransaction txn3 = transactionService.getUserTransaction(false); - txn3.begin(); - - // Check the Vital Record data - assertFalse(vitalRecordService.getVitalRecordDefinition(nonVitalRecordCategory).isEnabled()); - assertFalse(vitalRecordService.getVitalRecordDefinition(nonVitalFolder).isEnabled()); - assertEquals("The Vital Record reviewPeriod in the folder did not match its parent category", - vitalRecordService.getVitalRecordDefinition(nonVitalFolder).getReviewPeriod(), - vitalRecordService.getVitalRecordDefinition(nonVitalRecordCategory).getReviewPeriod()); - - // Create a record - NodeRef nonVitalRecord = this.nodeService.createNode(nonVitalFolder, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "MyNonVitalRecord.txt"), - ContentModel.TYPE_CONTENT).getChildRef(); - - // Set content - writer = this.contentService.getWriter(nonVitalRecord, ContentModel.PROP_CONTENT, true); - writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); - writer.setEncoding("UTF-8"); - writer.putContent("There is some content in this record"); - - this.rmActionService.executeRecordsManagementAction(nonVitalRecord, "file"); - - txn3.commit(); - - UserTransaction txn4 = transactionService.getUserTransaction(false); - txn4.begin(); - - // Check the review schedule - assertFalse(this.nodeService.hasAspect(nonVitalRecord, ASPECT_VITAL_RECORD)); - assertFalse(vitalRecordService.getVitalRecordDefinition(nonVitalRecord).isEnabled()); - assertEquals("The Vital Record reviewPeriod did not match its parent category", - vitalRecordService.getVitalRecordDefinition(nonVitalRecord).getReviewPeriod(), - vitalRecordService.getVitalRecordDefinition(nonVitalFolder).getReviewPeriod()); - - // Declare as a record - assertTrue(this.nodeService.hasAspect(nonVitalRecord, ASPECT_RECORD)); - - assertTrue("Declared record already on prior to test", - this.nodeService.hasAspect(nonVitalRecord, ASPECT_DECLARED_RECORD) == false); - - - this.nodeService.setProperty(nonVitalRecord, RecordsManagementModel.PROP_PUBLICATION_DATE, new Date()); - List smList = new ArrayList(2); - smList.add(FOUO); - smList.add(NOFORN); - this.nodeService.setProperty(nonVitalRecord, RecordsManagementModel.PROP_SUPPLEMENTAL_MARKING_LIST, (Serializable)smList); - this.nodeService.setProperty(nonVitalRecord, RecordsManagementModel.PROP_MEDIA_TYPE, "mediaTypeValue"); - this.nodeService.setProperty(nonVitalRecord, RecordsManagementModel.PROP_FORMAT, "formatValue"); - this.nodeService.setProperty(nonVitalRecord, RecordsManagementModel.PROP_DATE_RECEIVED, new Date()); - this.nodeService.setProperty(nonVitalRecord, RecordsManagementModel.PROP_ORIGINATOR, "origValue"); - this.nodeService.setProperty(nonVitalRecord, RecordsManagementModel.PROP_ORIGINATING_ORGANIZATION, "origOrgValue"); - this.nodeService.setProperty(nonVitalRecord, ContentModel.PROP_TITLE, "titleValue"); - - this.rmActionService.executeRecordsManagementAction(nonVitalRecord, "declareRecord"); - assertTrue(this.nodeService.hasAspect(nonVitalRecord, ASPECT_RECORD)); - assertTrue("Declared aspect not set", this.nodeService.hasAspect(nonVitalRecord, ASPECT_DECLARED_RECORD)); - - // - // Now we will change the vital record indicator in the containers above these records - // and ensure that the change is reflected down to the record. - // - - // 1. Switch parent folder from non-vital to vital. - this.nodeService.setProperty(nonVitalFolder, PROP_VITAL_RECORD_INDICATOR, true); - this.nodeService.setProperty(nonVitalFolder, PROP_REVIEW_PERIOD, "week|1"); - - txn4.commit(); - - UserTransaction txn5 = transactionService.getUserTransaction(false); - txn5.begin(); - - // check the folder search aspect - checkSearchAspect(nonVitalFolder); - - NodeRef formerlyNonVitalRecord = nonVitalRecord; - - assertTrue("Expected VitalRecord aspect not present", nodeService.hasAspect(formerlyNonVitalRecord, ASPECT_VITAL_RECORD)); - VitalRecordDefinition formerlyNonVitalRecordDefinition = vitalRecordService.getVitalRecordDefinition(formerlyNonVitalRecord); - assertNotNull(formerlyNonVitalRecordDefinition); - - assertEquals("The Vital Record reviewPeriod is wrong.", new Period("week|1"), - vitalRecordService.getVitalRecordDefinition(formerlyNonVitalRecord).getReviewPeriod()); - assertNotNull("formerlyNonVitalRecord should now have a reviewAsOf date.", - nodeService.getProperty(formerlyNonVitalRecord, PROP_REVIEW_AS_OF)); - - // check search aspect for the new vital record - checkSearchAspect(formerlyNonVitalRecord); - - // 2. Switch parent folder from vital to non-vital. - this.nodeService.setProperty(vitalRecFolder, PROP_VITAL_RECORD_INDICATOR, false); - - txn5.commit(); - - UserTransaction txn6 = transactionService.getUserTransaction(false); - txn6.begin(); - - NodeRef formerlyVitalRecord = vitalRecord; - - assertTrue("Unexpected VitalRecord aspect present", - nodeService.hasAspect(formerlyVitalRecord, ASPECT_VITAL_RECORD) == false); - VitalRecordDefinition formerlyVitalRecordDefinition = vitalRecordService.getVitalRecordDefinition(formerlyVitalRecord); - assertNotNull(formerlyVitalRecordDefinition); - assertNull("formerlyVitalRecord should now not have a reviewAsOf date.", - nodeService.getProperty(formerlyVitalRecord, PROP_REVIEW_AS_OF)); - - // 3. override the VitalRecordDefinition between Category, Folder, Record and ensure - // the overrides work - - // First switch the non-vital record folder back to vital. - this.nodeService.setProperty(vitalRecFolder, PROP_VITAL_RECORD_INDICATOR, true); - - txn6.commit(); - UserTransaction txn7 = transactionService.getUserTransaction(false); - txn7.begin(); - - assertTrue("Unexpected VitalRecord aspect present", - nodeService.hasAspect(vitalRecord, ASPECT_VITAL_RECORD)); - - // The reviewAsOf date should be changing as the parent review periods are updated. - Date initialReviewAsOfDate = (Date)nodeService.getProperty(vitalRecord, PROP_REVIEW_AS_OF); - assertNotNull("record should have a reviewAsOf date.", - initialReviewAsOfDate); - - // Change some of the VitalRecordDefinition in Record Category - Map recCatProps = this.nodeService.getProperties(vitalRecCategory); - - // Run this test twice (after a clean db) and it fails at the below line. - assertEquals(new Period("week|1"), recCatProps.get(PROP_REVIEW_PERIOD)); - this.nodeService.setProperty(vitalRecCategory, PROP_REVIEW_PERIOD, new Period("day|1")); - - txn7.commit(); - UserTransaction txn8 = transactionService.getUserTransaction(false); - txn8.begin(); - - assertEquals(new Period("day|1"), vitalRecordService.getVitalRecordDefinition(vitalRecCategory).getReviewPeriod()); - assertEquals(new Period("day|1"), vitalRecordService.getVitalRecordDefinition(vitalRecFolder).getReviewPeriod()); - - // check the search aspect of the folder after period change - checkSearchAspect(vitalRecFolder); - - // Change some of the VitalRecordDefinition in Record Folder - Map folderProps = this.nodeService.getProperties(vitalRecFolder); - assertEquals(new Period("day|1"), folderProps.get(PROP_REVIEW_PERIOD)); - this.nodeService.setProperty(vitalRecFolder, PROP_REVIEW_PERIOD, new Period("month|1")); - - txn8.commit(); - UserTransaction txn9 = transactionService.getUserTransaction(false); - txn9.begin(); - - assertEquals(new Period("day|1"), vitalRecordService.getVitalRecordDefinition(vitalRecCategory).getReviewPeriod()); - assertEquals(new Period("month|1"), vitalRecordService.getVitalRecordDefinition(vitalRecFolder).getReviewPeriod()); - - // check the search aspect of the folder after period change - checkSearchAspect(vitalRecFolder); - - // Need to commit the transaction to trigger the behaviour that handles changes to VitalRecord Definition. - txn9.commit(); - UserTransaction txn10 = transactionService.getUserTransaction(false); - txn10.begin(); - - Date newReviewAsOfDate = (Date)nodeService.getProperty(vitalRecord, PROP_REVIEW_AS_OF); - assertNotNull("record should have a reviewAsOf date.", initialReviewAsOfDate); - assertTrue("reviewAsOfDate should have changed.", - initialReviewAsOfDate.toString().equals(newReviewAsOfDate.toString()) == false); - - // check the search aspect of the record after period change - checkSearchAspect(vitalRecord); - - // Now clean up after this test. - nodeService.deleteNode(vitalRecord); - nodeService.deleteNode(vitalRecFolder); - nodeService.deleteNode(nonVitalRecord); - nodeService.deleteNode(nonVitalFolder); - nodeService.setProperty(vitalRecCategory, PROP_REVIEW_PERIOD, new Period("week|1")); - - txn10.commit(); - } - -} diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/system/RecordsManagementServiceImplSystemTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/system/RecordsManagementServiceImplSystemTest.java deleted file mode 100644 index 7ca0a52d65..0000000000 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/system/RecordsManagementServiceImplSystemTest.java +++ /dev/null @@ -1,812 +0,0 @@ -/* - * Copyright (C) 2005-2011 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.system; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.transaction.UserTransaction; - -import org.alfresco.model.ContentModel; -import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; -import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementActionService; -import org.alfresco.module.org_alfresco_module_rm.action.impl.BroadcastDispositionActionDefinitionUpdateAction; -import org.alfresco.module.org_alfresco_module_rm.action.impl.FileAction; -import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionAction; -import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition; -import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule; -import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService; -import org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEvent; -import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; -import org.alfresco.module.org_alfresco_module_rm.test.util.TestUtilities; -import org.alfresco.module.org_alfresco_module_rm.vital.VitalRecordDefinition; -import org.alfresco.module.org_alfresco_module_rm.vital.VitalRecordService; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.service.cmr.model.FileFolderService; -import org.alfresco.service.cmr.model.FileInfo; -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.Period; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.search.SearchService; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.namespace.RegexQNamePattern; -import org.alfresco.service.transaction.TransactionService; -import org.alfresco.util.BaseSpringTest; - -/** - * System test for records management service. - * - * Awaiting refactoring into records management test. - * - * @author Roy Wetherall - */ -public class RecordsManagementServiceImplSystemTest extends BaseSpringTest implements RecordsManagementModel -{ - protected static StoreRef SPACES_STORE = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore"); - - private NodeRef filePlan; - - private FileFolderService fileFolderService; - private NodeService nodeService; - private NodeService unprotectedNodeService; - private RecordsManagementActionService rmActionService; - private RecordsManagementService rmService; - private SearchService searchService; - private TransactionService transactionService; - private RetryingTransactionHelper transactionHelper; - private DispositionService dispositionService; - private VitalRecordService vitalRecordService; - - @Override - protected void onSetUpInTransaction() throws Exception - { - super.onSetUpInTransaction(); - - // Get the service required in the tests - this.fileFolderService = (FileFolderService)this.applicationContext.getBean("FileFolderService"); - this.nodeService = (NodeService)this.applicationContext.getBean("NodeService"); - this.unprotectedNodeService = (NodeService)this.applicationContext.getBean("nodeService"); - this.transactionService = (TransactionService)this.applicationContext.getBean("TransactionService"); - this.searchService = (SearchService)this.applicationContext.getBean("searchService"); - this.rmActionService = (RecordsManagementActionService)this.applicationContext.getBean("recordsManagementActionService"); - this.rmService = (RecordsManagementService)this.applicationContext.getBean("recordsManagementService"); - this.transactionHelper = (RetryingTransactionHelper)this.applicationContext.getBean("retryingTransactionHelper"); - this.dispositionService = (DispositionService)this.applicationContext.getBean("dispositionService"); - vitalRecordService = (VitalRecordService)applicationContext.getBean("VitalRecordService"); - - // Set the current security context as admin - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); - - // Get the test data - setUpTestData(); - } - - private void setUpTestData() - { - filePlan = TestUtilities.loadFilePlanData(applicationContext); - } - - @Override - protected void onTearDownInTransaction() throws Exception - { - try - { - UserTransaction txn = transactionService.getUserTransaction(false); - txn.begin(); - this.nodeService.deleteNode(filePlan); - txn.commit(); - } - catch (Exception e) - { - // Nothing - //System.out.println("DID NOT DELETE FILE PLAN!"); - } - } - - public void testDispositionPresence() throws Exception - { - setComplete(); - endTransaction(); - - // create a record category node in - final NodeRef nodeRef = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - NodeRef rootNode = nodeService.getRootNode(SPACES_STORE); - Map props = new HashMap(1); - String recordCategoryName = "Test Record Category"; - props.put(ContentModel.PROP_NAME, recordCategoryName); - NodeRef result = nodeService.createNode(rootNode, ContentModel.ASSOC_CHILDREN, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(recordCategoryName)), - TYPE_RECORD_CATEGORY, props).getChildRef(); - return result; - } - }); - - - // ensure the record category node has the scheduled aspect and the disposition schedule association - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - assertTrue(nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_SCHEDULED)); - List scheduleAssocs = nodeService.getChildAssocs(nodeRef, ASSOC_DISPOSITION_SCHEDULE, RegexQNamePattern.MATCH_ALL); - - - assertNotNull(scheduleAssocs); - assertEquals(1, scheduleAssocs.size()); - - // test retrieval of the disposition schedule via RM service - DispositionSchedule schedule = dispositionService.getDispositionSchedule(nodeRef); - assertNotNull(schedule); - return null; - } - }); - } - - /** - * This test method contains a subset of the tests in TC 7-2 of the DoD doc. - * @throws Exception - */ - public void testRescheduleRecord_IsNotCutOff() throws Exception - { - final NodeRef recCat = TestUtilities.getRecordCategory(rmService, nodeService, "Reports", "AIS Audit Records"); - // This RC has disposition instructions "Cut off monthly, hold 1 month, then destroy." - - setComplete(); - endTransaction(); - - // Create a suitable folder for this test. - final NodeRef testFolder = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - Map folderProps = new HashMap(1); - String folderName = "testFolder" + System.currentTimeMillis(); - folderProps.put(ContentModel.PROP_NAME, folderName); - NodeRef recordFolder = nodeService.createNode(recCat, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, folderName), - TYPE_RECORD_FOLDER).getChildRef(); - return recordFolder; - } - }); - - // Create a record in the test folder. File it and declare it. - final NodeRef testRecord = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - final NodeRef result = nodeService.createNode(testFolder, ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, - "Record" + System.currentTimeMillis() + ".txt"), - ContentModel.TYPE_CONTENT).getChildRef(); - - rmActionService.executeRecordsManagementAction(result, "file"); - TestUtilities.declareRecord(result, unprotectedNodeService, rmActionService); - return result; - } - }); - - assertTrue("recCat missing scheduled aspect", nodeService.hasAspect(recCat, RecordsManagementModel.ASPECT_SCHEDULED)); - assertFalse("folder should not have scheduled aspect", nodeService.hasAspect(testFolder, RecordsManagementModel.ASPECT_SCHEDULED)); - assertFalse("record should not have scheduled aspect", nodeService.hasAspect(testRecord, RecordsManagementModel.ASPECT_SCHEDULED)); - - assertFalse("recCat should not have dispositionLifecycle aspect", nodeService.hasAspect(recCat, RecordsManagementModel.ASPECT_DISPOSITION_LIFECYCLE)); - assertTrue("testFolder missing dispositionLifecycle aspect", nodeService.hasAspect(testFolder, RecordsManagementModel.ASPECT_DISPOSITION_LIFECYCLE)); - assertFalse("testRecord should not have dispositionLifecycle aspect", nodeService.hasAspect(testRecord, RecordsManagementModel.ASPECT_DISPOSITION_LIFECYCLE)); - - // Change the cutoff conditions for the associated record category - final Date dateBeforeChange = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Date execute() throws Throwable - { - Date asOfDate = dispositionService.getNextDispositionAction(testFolder).getAsOfDate(); - System.out.println("Going to change the disposition asOf Date."); - System.out.println(" - Original value: " + asOfDate); - - // Now change "Cut off monthly, hold 1 month, then destroy." - // to "Cut off yearly, hold 1 month, then destroy." - List dads = dispositionService.getDispositionSchedule(testFolder).getDispositionActionDefinitions(); - DispositionActionDefinition firstDAD = dads.get(0); - assertEquals("cutoff", firstDAD.getName()); - NodeRef dadNode = firstDAD.getNodeRef(); - - nodeService.setProperty(dadNode, PROP_DISPOSITION_PERIOD, new Period("year|1")); - - List updatedProps = new ArrayList(1); - updatedProps.add(PROP_DISPOSITION_PERIOD); - refreshDispositionActionDefinition(dadNode, updatedProps); - - return asOfDate; - } - }); - - // view the record metadata to verify that the record has been rescheduled. - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - DispositionAction nextDispositionAction = dispositionService.getNextDispositionAction(testFolder); - - assertEquals("cutoff", nextDispositionAction.getName()); - Date asOfDateAfterChange = nextDispositionAction.getAsOfDate(); - System.out.println(" - Updated value: " + asOfDateAfterChange); - - assertFalse("Expected disposition asOf date to change.", asOfDateAfterChange.equals(dateBeforeChange)); - return null; - } - }); - - // Change the disposition type (e.g. time-based to event-based) - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - List rmes = dispositionService.getNextDispositionAction(testFolder).getDispositionActionDefinition().getEvents(); - System.out.println("Going to change the RMEs."); - System.out.println(" - Original value: " + rmes); - - List dads = dispositionService.getDispositionSchedule(testFolder).getDispositionActionDefinitions(); - DispositionActionDefinition firstDAD = dads.get(0); - assertEquals("cutoff", firstDAD.getName()); - NodeRef dadNode = firstDAD.getNodeRef(); - -// nodeService.setProperty(dadNode, PROP_DISPOSITION_PERIOD, null); - List eventNames= new ArrayList(); - eventNames.add("study_complete"); - nodeService.setProperty(dadNode, PROP_DISPOSITION_EVENT, (Serializable)eventNames); - - return null; - } - }); - // Now add a second event to the same - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - DispositionAction nextDispositionAction = dispositionService.getNextDispositionAction(testFolder); - StringBuilder buf = new StringBuilder(); - for (RecordsManagementEvent e : nextDispositionAction.getDispositionActionDefinition().getEvents()) { - buf.append(e.getName()).append(','); - } - - System.out.println("Going to change the RMEs again."); - System.out.println(" - Original value: " + buf.toString()); - - List dads = dispositionService.getDispositionSchedule(testFolder).getDispositionActionDefinitions(); - DispositionActionDefinition firstDAD = dads.get(0); - assertEquals("cutoff", firstDAD.getName()); - NodeRef dadNode = firstDAD.getNodeRef(); - - List eventNames= new ArrayList(); - eventNames.add("study_complete"); - eventNames.add("case_complete"); - nodeService.setProperty(dadNode, PROP_DISPOSITION_EVENT, (Serializable)eventNames); - - return null; - } - }); - - // View the record metadata to verify that the record has been rescheduled. - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - DispositionAction nextDispositionAction = dispositionService.getNextDispositionAction(testFolder); - - assertEquals("cutoff", nextDispositionAction.getName()); - StringBuilder buf = new StringBuilder(); - for (RecordsManagementEvent e : nextDispositionAction.getDispositionActionDefinition().getEvents()) { - buf.append(e.getName()).append(','); - } - System.out.println(" - Updated value: " + buf.toString()); - - assertFalse("Disposition should not be eligible.", nextDispositionAction.isEventsEligible()); - return null; - } - }); - - // Tidy up test nodes. - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - nodeService.deleteNode(testRecord); - - // Change the disposition Period back to what it was. - List dads = dispositionService.getDispositionSchedule(testFolder).getDispositionActionDefinitions(); - DispositionActionDefinition firstDAD = dads.get(0); - assertEquals("cutoff", firstDAD.getName()); - NodeRef dadNode = firstDAD.getNodeRef(); - nodeService.setProperty(dadNode, PROP_DISPOSITION_PERIOD, new Period("month|1")); - - nodeService.deleteNode(testFolder); - - return null; - } - }); - } - - private void refreshDispositionActionDefinition(NodeRef nodeRef, List updatedProps) - { - if (updatedProps != null) - { - Map params = new HashMap(); - params.put(BroadcastDispositionActionDefinitionUpdateAction.CHANGED_PROPERTIES, (Serializable)updatedProps); - rmActionService.executeRecordsManagementAction(nodeRef, BroadcastDispositionActionDefinitionUpdateAction.NAME, params); - } - - // Remove the unpublished update aspect - nodeService.removeAspect(nodeRef, ASPECT_UNPUBLISHED_UPDATE); - } - - public void testGetDispositionInstructions() throws Exception - { - setComplete(); - endTransaction(); - - // Get a record - // TODO - - // Get a record folder - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - NodeRef folderRecord = TestUtilities.getRecordFolder(rmService, nodeService, "Reports", "AIS Audit Records", "January AIS Audit Records"); - assertNotNull(folderRecord); - assertEquals("January AIS Audit Records", nodeService.getProperty(folderRecord, ContentModel.PROP_NAME)); - - assertFalse(rmService.isRecord(folderRecord)); - assertTrue(rmService.isRecordFolder(folderRecord)); - assertFalse(rmService.isRecordCategory(folderRecord)); - - DispositionSchedule di = dispositionService.getDispositionSchedule(folderRecord); - assertNotNull(di); - assertEquals("N1-218-00-4 item 023", di.getDispositionAuthority()); - assertEquals("Cut off monthly, hold 1 month, then destroy.", di.getDispositionInstructions()); - assertFalse(di.isRecordLevelDisposition()); - - // Get a record category - NodeRef recordCategory = TestUtilities.getRecordCategory(rmService, nodeService, "Reports", "AIS Audit Records"); - assertNotNull(recordCategory); - assertEquals("AIS Audit Records", nodeService.getProperty(recordCategory, ContentModel.PROP_NAME)); - - assertFalse(rmService.isRecord(recordCategory)); - assertFalse(rmService.isRecordFolder(recordCategory)); - assertTrue(rmService.isRecordCategory(recordCategory)); - - di = dispositionService.getDispositionSchedule(recordCategory); - assertNotNull(di); - assertEquals("N1-218-00-4 item 023", di.getDispositionAuthority()); - assertEquals("Cut off monthly, hold 1 month, then destroy.", di.getDispositionInstructions()); - assertFalse(di.isRecordLevelDisposition()); - - List das = di.getDispositionActionDefinitions(); - assertNotNull(das); - assertEquals(2, das.size()); - assertEquals("cutoff", das.get(0).getName()); - assertEquals("destroy", das.get(1).getName()); - return null; - } - }); - } - - public void testMoveRecordWithinFileplan() - { - setComplete(); - endTransaction(); - - // We need record folders for test-filing as follows: - // 1. A 'clean' record folder with no disposition schedult and no review period. - // 2. A 'vital' record folder which has a review period defined. - // 3. A 'dispositionable' record folder which has an applicable disposition schedule. - // - // The example fileplan includes a folder which covers [2] and [3] together. - - final NodeRef cleanRecordFolder = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - NodeRef result = TestUtilities.getRecordFolder(rmService, nodeService, "Civilian Files", "Case Files and Papers", "Gilbert Competency Hearing"); - assertNotNull("cleanRecordFolder was null", result); - - final DispositionSchedule dispositionSchedule = dispositionService.getDispositionSchedule(result); - assertNull("cleanRecordFolder had non-null disposition instructions.", dispositionSchedule.getDispositionInstructions()); - assertTrue("cleanRecordFolder had non-empty disposition instruction definitions.", dispositionSchedule.getDispositionActionDefinitions().isEmpty()); - - final VitalRecordDefinition vitalRecordDefinition = vitalRecordService.getVitalRecordDefinition(result); - assertEquals("cleanRecordFolder had wrong review period.", "0", vitalRecordDefinition.getReviewPeriod().getExpression()); - assertNull("cleanRecordFolder had non-null review date.", vitalRecordDefinition.getNextReviewDate()); - return result; - } - }); - final NodeRef dispAndVitalRecordFolder = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - NodeRef result = TestUtilities.getRecordFolder(rmService, nodeService, "Reports", "AIS Audit Records", "January AIS Audit Records"); - assertNotNull("dispositionAndVitalRecordFolder was null", result); - - final DispositionSchedule dispositionSchedule = dispositionService.getDispositionSchedule(result); - assertNotNull("dispositionAndVitalRecordFolder had null disposition instructions.", dispositionSchedule.getDispositionInstructions()); - assertFalse("dispositionAndVitalRecordFolder had empty disposition instruction definitions.", dispositionSchedule.getDispositionActionDefinitions().isEmpty()); - - final VitalRecordDefinition vitalRecordDefinition = vitalRecordService.getVitalRecordDefinition(result); - assertFalse("dispositionAndVitalRecordFolder had wrong review period.", "none|0".equals(vitalRecordDefinition.getReviewPeriod().getExpression())); - assertNotNull("dispositionAndVitalRecordFolder had null review date.", vitalRecordDefinition.getNextReviewDate()); - return result; - } - }); - - // Create a record in the 'clean' folder. - final NodeRef testRecord = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - final NodeRef result = nodeService.createNode(cleanRecordFolder, ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, - "Record" + System.currentTimeMillis() + ".txt"), - ContentModel.TYPE_CONTENT).getChildRef(); - - rmActionService.executeRecordsManagementAction(result, "file"); - TestUtilities.declareRecord(result, unprotectedNodeService, rmActionService); - return result; - } - }); - - // Ensure it's devoid of all disposition and review-related state. - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - final DispositionSchedule dispositionSchedule = dispositionService.getDispositionSchedule(testRecord); - assertNull("testRecord had non-null disposition instructions.", dispositionSchedule.getDispositionInstructions()); - assertTrue("testRecord had non-empty disposition instruction definitions.", dispositionSchedule.getDispositionActionDefinitions().isEmpty()); - - final VitalRecordDefinition vitalRecordDefinition = vitalRecordService.getVitalRecordDefinition(testRecord); - assertEquals("testRecord had wrong review period.", "0", vitalRecordDefinition.getReviewPeriod().getExpression()); - assertNull("testRecord had non-null review date.", vitalRecordDefinition.getNextReviewDate()); - return null; - } - }); - - // Move from non-vital to vital - also non-dispositionable to dispositionable at the same time. - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - nodeService.moveNode(testRecord, dispAndVitalRecordFolder, ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS); - return null; - } - }); - - // Assert that the disposition and review-related data are correct after the move. - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - final DispositionSchedule dispositionSchedule = dispositionService.getDispositionSchedule(testRecord); - assertNotNull("testRecord had null disposition instructions.", dispositionSchedule.getDispositionInstructions()); - assertFalse("testRecord had empty disposition instruction definitions.", dispositionSchedule.getDispositionActionDefinitions().isEmpty()); - - final VitalRecordDefinition vitalRecordDefinition = vitalRecordService.getVitalRecordDefinition(testRecord); - assertFalse("testRecord had wrong review period.", "0".equals(vitalRecordDefinition.getReviewPeriod().getExpression())); - assertNotNull("testRecord had null review date.", vitalRecordDefinition.getNextReviewDate()); - return null; - } - }); - - // Move the test record back from vital to non-vital - also dispositionable to non-dispositionable at the same time. - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - nodeService.moveNode(testRecord, cleanRecordFolder, ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS); - return null; - } - }); - - // Assert that the disposition and review-related data are correct after the move. - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - final DispositionSchedule dispositionSchedule = dispositionService.getDispositionSchedule(testRecord); - assertNull("testRecord had non-null disposition instructions.", dispositionSchedule.getDispositionInstructions()); - assertTrue("testRecord had non-empty disposition instruction definitions.", dispositionSchedule.getDispositionActionDefinitions().isEmpty()); - - final VitalRecordDefinition vitalRecordDefinition = vitalRecordService.getVitalRecordDefinition(testRecord); - assertEquals("testRecord had wrong review period.", "0", vitalRecordDefinition.getReviewPeriod().getExpression()); - assertNull("testRecord had non-null review date.", vitalRecordDefinition.getNextReviewDate()); - return null; - } - }); - - //TODO check the search aspect - - // Tidy up. - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - nodeService.deleteNode(testRecord); - - return null; - } - }); - } - - public void testCopyRecordWithinFileplan() - { - setComplete(); - endTransaction(); - - // We need record folders for test-filing as follows: - // 1. A 'clean' record folder with no disposition schedule and no review period. - // 2. A 'vital' record folder which has a review period defined. - // 3. A 'dispositionable' record folder which has an applicable disposition schedule. - // - // The example fileplan includes a folder which covers [2] and [3] together. - - final NodeRef cleanRecordFolder = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - NodeRef result = TestUtilities.getRecordFolder(rmService, nodeService, "Civilian Files", "Case Files and Papers", "Gilbert Competency Hearing"); - assertNotNull("cleanRecordFolder was null", result); - - final DispositionSchedule dispositionSchedule = dispositionService.getDispositionSchedule(result); - assertNull("cleanRecordFolder had non-null disposition instructions.", dispositionSchedule.getDispositionInstructions()); - assertTrue("cleanRecordFolder had non-empty disposition instruction definitions.", dispositionSchedule.getDispositionActionDefinitions().isEmpty()); - - final VitalRecordDefinition vitalRecordDefinition = vitalRecordService.getVitalRecordDefinition(result); - assertEquals("cleanRecordFolder had wrong review period.", "0", vitalRecordDefinition.getReviewPeriod().getExpression()); - assertNull("cleanRecordFolder had non-null review date.", vitalRecordDefinition.getNextReviewDate()); - return result; - } - }); - final NodeRef dispAndVitalRecordFolder = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - NodeRef result = TestUtilities.getRecordFolder(rmService, nodeService, "Reports", "AIS Audit Records", "January AIS Audit Records"); - assertNotNull("dispositionAndVitalRecordFolder was null", result); - - final DispositionSchedule dispositionSchedule = dispositionService.getDispositionSchedule(result); - assertNotNull("dispositionAndVitalRecordFolder had null disposition instructions.", dispositionSchedule.getDispositionInstructions()); - assertFalse("dispositionAndVitalRecordFolder had empty disposition instruction definitions.", dispositionSchedule.getDispositionActionDefinitions().isEmpty()); - - final VitalRecordDefinition vitalRecordDefinition = vitalRecordService.getVitalRecordDefinition(result); - assertFalse("dispositionAndVitalRecordFolder had wrong review period.", "none|0".equals(vitalRecordDefinition.getReviewPeriod().getExpression())); - assertNotNull("dispositionAndVitalRecordFolder had null review date.", vitalRecordDefinition.getNextReviewDate()); - return result; - } - }); - - // Create a record in the 'clean' folder. - final NodeRef testRecord = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - final NodeRef result = nodeService.createNode(cleanRecordFolder, ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, - "Record" + System.currentTimeMillis() + ".txt"), - ContentModel.TYPE_CONTENT).getChildRef(); - - rmActionService.executeRecordsManagementAction(result, "file"); - TestUtilities.declareRecord(result, unprotectedNodeService, rmActionService); - return result; - } - }); - - // Ensure it's devoid of all disposition and review-related state. - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - final DispositionSchedule dispositionSchedule = dispositionService.getDispositionSchedule(testRecord); - assertNull("testRecord had non-null disposition instructions.", dispositionSchedule.getDispositionInstructions()); - assertTrue("testRecord had non-empty disposition instruction definitions.", dispositionSchedule.getDispositionActionDefinitions().isEmpty()); - - final VitalRecordDefinition vitalRecordDefinition = vitalRecordService.getVitalRecordDefinition(testRecord); - assertEquals("testRecord had wrong review period.", "0", vitalRecordDefinition.getReviewPeriod().getExpression()); - assertNull("testRecord had non-null review date.", vitalRecordDefinition.getNextReviewDate()); - return null; - } - }); - - // Copy from non-vital to vital - also non-dispositionable to dispositionable at the same time. - final NodeRef copiedNode = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - FileInfo fileInfo = fileFolderService.copy(testRecord, dispAndVitalRecordFolder, null); - NodeRef n = fileInfo.getNodeRef(); - return n; - } - }); - - // Assert that the disposition and review-related data are correct after the copy. - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - final DispositionSchedule dispositionSchedule = dispositionService.getDispositionSchedule(copiedNode); - assertNotNull("copiedNode had null disposition instructions.", dispositionSchedule.getDispositionInstructions()); - assertFalse("copiedNode had empty disposition instruction definitions.", dispositionSchedule.getDispositionActionDefinitions().isEmpty()); - - final VitalRecordDefinition vitalRecordDefinition = vitalRecordService.getVitalRecordDefinition(copiedNode); - assertFalse("copiedNode had wrong review period.", "0".equals(vitalRecordDefinition.getReviewPeriod().getExpression())); - assertNotNull("copiedNode had null review date.", vitalRecordDefinition.getNextReviewDate()); - return null; - } - }); - - // Create a record in the 'vital and disposition' folder. - final NodeRef testRecord2 = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - final NodeRef result = nodeService.createNode(dispAndVitalRecordFolder, ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, - "Record2" + System.currentTimeMillis() + ".txt"), - ContentModel.TYPE_CONTENT).getChildRef(); - - rmActionService.executeRecordsManagementAction(result, "file"); - TestUtilities.declareRecord(result, unprotectedNodeService, rmActionService); - return result; - } - }); - - // Check the vital and disposition status. - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - final DispositionSchedule dispositionSchedule = dispositionService.getDispositionSchedule(testRecord2); - assertNotNull("testRecord2 had null disposition instructions.", dispositionSchedule.getDispositionInstructions()); - assertFalse("testRecord2 had empty disposition instruction definitions.", dispositionSchedule.getDispositionActionDefinitions().isEmpty()); - - final VitalRecordDefinition vitalRecordDefinition = vitalRecordService.getVitalRecordDefinition(testRecord2); - assertFalse("testRecord2 had wrong review period.", "0".equals(vitalRecordDefinition.getReviewPeriod().getExpression())); - assertNotNull("testRecord2 had null review date.", vitalRecordDefinition.getNextReviewDate()); - return null; - } - }); - - // copy the record back from vital to non-vital - also dispositionable to non-dispositionable at the same time. - final NodeRef copiedBackNode = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - FileInfo fileInfo = fileFolderService.copy(testRecord2, cleanRecordFolder, null); // TODO Something wrong here. - NodeRef n = fileInfo.getNodeRef(); - return n; - } - }); - - // Assert that the disposition and review-related data are correct after the copy-back. - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - final DispositionSchedule dispositionSchedule = dispositionService.getDispositionSchedule(copiedBackNode); - assertNull("copiedBackNode had non-null disposition instructions.", dispositionSchedule.getDispositionInstructions()); - assertTrue("copiedBackNode had non-empty disposition instruction definitions.", dispositionSchedule.getDispositionActionDefinitions().isEmpty()); - - final VitalRecordDefinition vitalRecordDefinition = vitalRecordService.getVitalRecordDefinition(copiedBackNode); - assertEquals("copiedBackNode had wrong review period.", "0", vitalRecordDefinition.getReviewPeriod().getExpression()); - assertNull("copiedBackNode had non-null review date.", vitalRecordDefinition.getNextReviewDate()); - return null; - } - }); - - //TODO check the search aspect - - // Tidy up. - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - nodeService.deleteNode(copiedBackNode); - nodeService.deleteNode(testRecord2); - nodeService.deleteNode(copiedNode); - nodeService.deleteNode(testRecord); - - return null; - } - }); - } - - public void xxxtestUpdateNextDispositionAction() - { - setComplete(); - endTransaction(); - - final FileAction fileAction = (FileAction)applicationContext.getBean("file"); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - // Get a record folder - NodeRef folderRecord = TestUtilities.getRecordFolder(rmService, nodeService, "Reports", "AIS Audit Records", "January AIS Audit Records"); - assertNotNull(folderRecord); - assertEquals("January AIS Audit Records", nodeService.getProperty(folderRecord, ContentModel.PROP_NAME)); - - DispositionSchedule di = dispositionService.getDispositionSchedule(folderRecord); - assertNotNull(di); - assertEquals("N1-218-00-4 item 023", di.getDispositionAuthority()); - assertEquals("Cut off monthly, hold 1 month, then destroy.", di.getDispositionInstructions()); - assertFalse(di.isRecordLevelDisposition()); - - assertFalse(nodeService.hasAspect(folderRecord, ASPECT_DISPOSITION_LIFECYCLE)); - - fileAction.updateNextDispositionAction(folderRecord); - - - // Check the next disposition action - assertTrue(nodeService.hasAspect(folderRecord, ASPECT_DISPOSITION_LIFECYCLE)); - NodeRef ndNodeRef = nodeService.getChildAssocs(folderRecord, ASSOC_NEXT_DISPOSITION_ACTION, RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(ndNodeRef); - assertEquals("cutoff", nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION)); - assertEquals(di.getDispositionActionDefinitions().get(0).getId(), nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION_ID)); - assertNotNull(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF)); - - // Check the history is empty - // TODO - - Map props = new HashMap(1); - props.put(PROP_CUT_OFF_DATE, new Date()); - unprotectedNodeService.addAspect(folderRecord, ASPECT_CUT_OFF, props); - fileAction.updateNextDispositionAction(folderRecord); - - assertTrue(nodeService.hasAspect(folderRecord, ASPECT_DISPOSITION_LIFECYCLE)); - ndNodeRef = nodeService.getChildAssocs(folderRecord, ASSOC_NEXT_DISPOSITION_ACTION, RegexQNamePattern.MATCH_ALL).get(0).getChildRef(); - assertNotNull(ndNodeRef); - assertEquals("destroy", nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION)); - assertEquals(di.getDispositionActionDefinitions().get(1).getId(), nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_ACTION_ID)); - assertNotNull(nodeService.getProperty(ndNodeRef, PROP_DISPOSITION_AS_OF)); - - // Check the history has an action - // TODO - - fileAction.updateNextDispositionAction(folderRecord); - - assertTrue(nodeService.hasAspect(folderRecord, ASPECT_DISPOSITION_LIFECYCLE)); - assertTrue(nodeService.getChildAssocs(folderRecord, ASSOC_NEXT_DISPOSITION_ACTION, RegexQNamePattern.MATCH_ALL).isEmpty()); - - // Check the history has both actions - // TODO - return null; - } - }); - } -} 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 0396b72697..72a67d5330 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 @@ -33,7 +33,7 @@ import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService import org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEventService; import org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; -import org.alfresco.module.org_alfresco_module_rm.model.RmSiteType; +import org.alfresco.module.org_alfresco_module_rm.model.behaviour.RmSiteType; import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.module.org_alfresco_module_rm.search.RecordsManagementSearchService; import org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService; @@ -43,6 +43,7 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil; 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.ContentService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; @@ -50,6 +51,7 @@ import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.MutableAuthenticationService; +import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.site.SiteInfo; import org.alfresco.service.cmr.site.SiteService; @@ -104,6 +106,8 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase protected AuthorityService authorityService; protected PersonService personService; protected TransactionService transactionService; + protected FileFolderService fileFolderService; + protected PermissionService permissionService; /** RM Services */ protected RecordsManagementService rmService; @@ -261,6 +265,8 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase authenticationService = (MutableAuthenticationService)this.applicationContext.getBean("AuthenticationService"); personService = (PersonService)this.applicationContext.getBean("PersonService"); transactionService = (TransactionService)applicationContext.getBean("TransactionService"); + fileFolderService = (FileFolderService)applicationContext.getBean("FileFolderService"); + permissionService = (PermissionService)applicationContext.getBean("PermissionService"); // Get RM services rmService = (RecordsManagementService)applicationContext.getBean("RecordsManagementService"); @@ -325,16 +331,15 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase */ protected void setupTestData() { - retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback() + doTestInTransaction(new Test() { - @Override - public Object execute() throws Throwable + public Void run() { - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); - setupTestDataImpl(); - return null; + setupTestDataImpl(); + return null; } - }); + }, + AuthenticationUtil.getSystemUserName()); } /** diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMWebScriptTestCase.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMWebScriptTestCase.java index f45947b6f1..50bcd6f5ba 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMWebScriptTestCase.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMWebScriptTestCase.java @@ -1,5 +1,20 @@ -/** - * +/* + * 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.test.util; @@ -17,7 +32,7 @@ import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedul import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService; import org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEventService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; -import org.alfresco.module.org_alfresco_module_rm.model.RmSiteType; +import org.alfresco.module.org_alfresco_module_rm.model.behaviour.RmSiteType; import org.alfresco.module.org_alfresco_module_rm.search.RecordsManagementSearchService; import org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService; import org.alfresco.module.org_alfresco_module_rm.vital.VitalRecordService; diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/TestUtilities.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/TestUtilities.java index 214e03d4a9..b14ddb239e 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/TestUtilities.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/TestUtilities.java @@ -35,7 +35,7 @@ import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementActionService; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; -import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementSearchBehaviour; +import org.alfresco.module.org_alfresco_module_rm.model.behaviour.RecordsManagementSearchBehaviour; import org.alfresco.module.org_alfresco_module_rm.script.BootstrapTestDataGet; import org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService; import org.alfresco.service.cmr.repository.ChildAssociationRef;