From fcabe577a33984e34920af51828dc6ab27cc82b8 Mon Sep 17 00:00:00 2001 From: Roy Wetherall Date: Thu, 24 Jan 2013 05:53:41 +0000 Subject: [PATCH] RM: Adjust the way the unfiled container is modelled and created. * means search and other navigation paths work correctly * will allow the navigation of the unfiled container via other UI's and API's much easier * created the file plan service * methods relating to the unfiled container now encapsulated in the file plan service * TODO move many of the methods in the records management service into the file plan service .. with the ultimate aim of deprecating the catch-all records management service! * delt with fall out from changes * relates to RM-583 NOTE: you will need to recreate any db's previously created on the 2.1 development branch ... any pre-2.1 will be fine and patch correctly. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@45823 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../org_alfresco_module_rm/action-context.xml | 1 + .../model/recordsModel.xml | 13 - .../rm-action-context.xml | 1 - .../rm-patch-context.xml | 3 +- .../rm-service-context.xml | 80 +++- .../rm-ui-evaluators-context.xml | 1 + .../documentlibrary-v2/rm-filters.lib.js | 3 +- .../documentlibrary/rm-treenode.get.js | 3 +- .../fileplan/FilePlanService.java | 37 ++ .../fileplan/FilePlanServiceImpl.java | 168 +++++++ .../jscript/app/JSONConversionComponent.java | 423 +++++++++--------- .../model/RecordsManagementModel.java | 1 - .../patch/RMv21InPlacePatch.java | 61 +-- .../record/RecordService.java | 9 - .../record/RecordServiceImpl.java | 49 +- .../recordfolder/RecordFolderService.java | 2 + .../role/FilePlanRoleServiceImpl.java | 55 +-- .../test/service/RecordServiceImplTest.java | 17 - .../test/util/BaseRMTestCase.java | 5 +- 19 files changed, 532 insertions(+), 400 deletions(-) create mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanService.java create mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanServiceImpl.java 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 index 6c42372145..a8239eee49 100644 --- 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 @@ -29,6 +29,7 @@ + \ No newline at end of file diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml index 6fe1ab88df..35335fb8e4 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml @@ -625,19 +625,6 @@ - - Unfiled Records - - true - false - - - rma:unfiledRecordContainer - true - true - - - rma:filePlanComponent 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 9a4f6534bd..68e3593260 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 @@ -274,7 +274,6 @@ - diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-patch-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-patch-context.xml index 0e48f81d15..827f3ca406 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-patch-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-patch-context.xml @@ -40,11 +40,10 @@ - - + \ No newline at end of file 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 a5584df207..047c7b0778 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 @@ -3,6 +3,31 @@ + + + + + + + + + ${server.transaction.mode.default} + + + + + + + + + + + + + + + + @@ -39,16 +64,7 @@ - - - - - - - ${server.transaction.mode.default} - - - + @@ -412,6 +428,46 @@ + + + + + + + + + + + + org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService + + + + + + + + + + + + + + + + + + + + + + @@ -482,7 +538,7 @@ - + @@ -1040,6 +1096,7 @@ + @@ -1087,7 +1144,6 @@ org.alfresco.module.org_alfresco_module_rm.record.RecordService.isDeclared=RM.Read.0 org.alfresco.module.org_alfresco_module_rm.record.RecordService.isFiled=RM.Read.0 org.alfresco.module.org_alfresco_module_rm.record.RecordService.createRecord=RM_ALLOW - org.alfresco.module.org_alfresco_module_rm.record.RecordService.getUnfiledContainer=RM.Read.0 org.alfresco.module.org_alfresco_module_rm.record.RecordService.*=RM_DENY ]]> diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml index a090f3e5c8..b733ec2682 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml @@ -8,6 +8,7 @@ parent="baseJsonConversionComponent"> + 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 fa31ed974e..a65ba7a246 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 @@ -38,7 +38,8 @@ Filters.IGNORED_TYPES = "rma:dispositionActionDefinition", "rma:dispositionAction", "rma:hold", - "rma:transfer" + "rma:transfer", + "rma:unfiledRecordContainer" ]; /** 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 8dd5e01d78..b4d8a009c1 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 @@ -16,7 +16,8 @@ function getTreenode() { "{http://www.alfresco.org/model/forum/1.0}forum": true, "{http://www.alfresco.org/model/forum/1.0}topic": true, - "{http://www.alfresco.org/model/content/1.0}systemfolder": true + "{http://www.alfresco.org/model/content/1.0}systemfolder": true, + "{http://www.alfresco.org/model/recordsmanagement/1.0}unfiledRecordContainer":true }, skipPermissionCheck = args["perms"] == "false", evalChildFolders = args["children"] !== "false", diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanService.java new file mode 100644 index 0000000000..14ba581eda --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanService.java @@ -0,0 +1,37 @@ +/* + * 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.fileplan; + +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * File plan service interface. + * + * @author Roy Wetherall + * @since 2.1 + */ +public interface FilePlanService +{ + boolean existsUnfiledContainer(NodeRef filePlan); + + NodeRef getUnfiledContainer(NodeRef filePlan); + + NodeRef createUnfiledContainer(NodeRef filePlan); + +} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanServiceImpl.java new file mode 100644 index 0000000000..4b04152756 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanServiceImpl.java @@ -0,0 +1,168 @@ +/* + * 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.fileplan; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; +import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService; +import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.ParameterCheck; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +/** + * File plan service implementation. + * + * @author Roy Wetherall + * @since 2.1 + */ +public class FilePlanServiceImpl implements FilePlanService, + RecordsManagementModel, + ApplicationContextAware +{ + /** Unfiled record container name */ + private static final String NAME_UNFILED_CONTAINER = "Unfiled Records"; + private static final QName QNAME_UNFILED_CONTAINER = QName.createQName(RM_URI, NAME_UNFILED_CONTAINER); + + /** Services */ + private NodeService nodeService; + private PermissionService permissionService; + private RecordsManagementService recordsManagementService; + + /** Application context */ + private ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException + { + this.applicationContext = applicationContext; + } + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + /** + * NOTE: for some reason spring couldn't cope with the circular references between these two + * beans so we need to grab this one manually. + * + * @return file plan role service + */ + public FilePlanRoleService getFilePlanRoleService() + { + return (FilePlanRoleService)applicationContext.getBean("FilePlanRoleService"); + } + + public void setPermissionService(PermissionService permissionService) + { + this.permissionService = permissionService; + } + + public void setRecordsManagementService(RecordsManagementService recordsManagementService) + { + this.recordsManagementService = recordsManagementService; + } + + @Override + public boolean existsUnfiledContainer(NodeRef filePlan) + { + return (getUnfiledContainer(filePlan) != null); + } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService#getUnfiledContainer(org.alfresco.service.cmr.repository.NodeRef) + */ + @Override + public NodeRef getUnfiledContainer(NodeRef filePlan) + { + ParameterCheck.mandatory("filePlan", filePlan); + if (recordsManagementService.isFilePlan(filePlan) == false) + { + throw new AlfrescoRuntimeException("Unable to get the unfiled container, because passed node is not a file plan."); + } + + NodeRef result = null; + + // try and get the unfiled record container + List assocs = nodeService.getChildAssocs(filePlan, ContentModel.ASSOC_CONTAINS, QNAME_UNFILED_CONTAINER); + if (assocs.size() > 1) + { + throw new AlfrescoRuntimeException("Unable to get unfiled conatiner."); + } + else + { + result = assocs.get(0).getChildRef(); + } + + return result; + } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService#createUnfiledContainer(org.alfresco.service.cmr.repository.NodeRef) + */ + public NodeRef createUnfiledContainer(NodeRef filePlan) + { + ParameterCheck.mandatory("filePlan", filePlan); + if (recordsManagementService.isFilePlan(filePlan) == false) + { + throw new AlfrescoRuntimeException("Unable to create unfiled container, because passed node is not a file plan."); + } + + String allRoles = getFilePlanRoleService().getAllRolesContainerGroup(filePlan); + + // create the properties map + Map properties = new HashMap(1); + properties.put(ContentModel.PROP_NAME, NAME_UNFILED_CONTAINER); + + // create the unfiled container + NodeRef container = nodeService.createNode( + filePlan, + ContentModel.ASSOC_CONTAINS, + QNAME_UNFILED_CONTAINER, + TYPE_UNFILED_RECORD_CONTAINER, + properties).getChildRef(); + + // set inheritance to false + permissionService.setInheritParentPermissions(container, false); + permissionService.setPermission(container, allRoles, RMPermissionModel.READ_RECORDS, true); + permissionService.setPermission(container, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS, true); + + // TODO set the admin users to have filing permissions on the unfiled container!!! + // TODO we will need to be able to get a list of the admin roles from the service + + return container; + } + + +} 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 e94d1a1ae2..4bac393f31 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.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.repository.NodeRef; @@ -40,233 +41,245 @@ import org.json.simple.JSONObject; */ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JSONConversionComponent { - /** Records management service */ - private RecordsManagementService recordsManagementService; + /** Records management service */ + private RecordsManagementService recordsManagementService; - /** Record service */ - private RecordService recordService; + /** Record service */ + private RecordService recordService; - /** Capability service */ - private CapabilityService capabilityService; + /** File plan service */ + private FilePlanService filePlanService; - /** Indicators */ - private List indicators = new ArrayList(); + /** Capability service */ + private CapabilityService capabilityService; - /** Actions */ - private List actions = new ArrayList(); + /** Indicators */ + private List indicators = new ArrayList(); - /** - * @param recordsManagementService records management service - */ - public void setRecordsManagementService(RecordsManagementService recordsManagementService) - { - this.recordsManagementService = recordsManagementService; - } + /** Actions */ + private List actions = new ArrayList(); - /** - * @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 capabilityService capability service - */ - public void setCapabilityService(CapabilityService capabilityService) - { - this.capabilityService = capabilityService; - } + /** + * @param recordService record service + */ + public void setRecordService(RecordService recordService) + { + this.recordService = recordService; + } - /** - * @param indicator registered indicator - */ - public void registerIndicator(BaseEvaluator indicator) - { - indicators.add(indicator); - } + /** + * @param filePlanService file plan service + */ + public void setFilePlanService(FilePlanService filePlanService) + { + this.filePlanService = filePlanService; + } - /** - * @param action registered action - */ - public void registerAction(BaseEvaluator action) - { - actions.add(action); - } + /** + * @param capabilityService capability service + */ + public void setCapabilityService(CapabilityService capabilityService) + { + this.capabilityService = capabilityService; + } - /** - * @see org.alfresco.repo.jscript.app.JSONConversionComponent#setRootValues(org.alfresco.service.cmr.model.FileInfo, org.json.simple.JSONObject, boolean) - */ - @SuppressWarnings("unchecked") - @Override - protected void setRootValues(FileInfo nodeInfo, JSONObject rootJSONObject, boolean useShortQNames) - { - // Set the base root values - super.setRootValues(nodeInfo, rootJSONObject, useShortQNames); + /** + * @param indicator registered indicator + */ + public void registerIndicator(BaseEvaluator indicator) + { + indicators.add(indicator); + } - // Get the node reference for convenience - NodeRef nodeRef = nodeInfo.getNodeRef(); + /** + * @param action registered action + */ + public void registerAction(BaseEvaluator action) + { + actions.add(action); + } - if (AccessStatus.ALLOWED.equals(capabilityService.getCapabilityAccessState(nodeRef, RMPermissionModel.VIEW_RECORDS)) == true) - { - // Indicate whether the node is a RM object or not - boolean isFilePlanComponent = recordsManagementService.isFilePlanComponent(nodeInfo.getNodeRef()); - rootJSONObject.put("isRmNode", isFilePlanComponent); + /** + * @see org.alfresco.repo.jscript.app.JSONConversionComponent#setRootValues(org.alfresco.service.cmr.model.FileInfo, + * org.json.simple.JSONObject, boolean) + */ + @SuppressWarnings("unchecked") + @Override + protected void setRootValues(FileInfo nodeInfo, JSONObject rootJSONObject, boolean useShortQNames) + { + // Set the base root values + super.setRootValues(nodeInfo, rootJSONObject, useShortQNames); - if (isFilePlanComponent == true) - { - rootJSONObject.put("rmNode", setRmNodeValues(nodeRef, rootJSONObject, useShortQNames)); - } - } - } + // Get the node reference for convenience + NodeRef nodeRef = nodeInfo.getNodeRef(); - /** - * - * @param nodeRef - * @param rootJSONObject - * @param useShortQName - * @return - */ - @SuppressWarnings("unchecked") - private JSONObject setRmNodeValues(NodeRef nodeRef, JSONObject rootJSONObject, boolean useShortQName) - { - JSONObject rmNodeValues = new JSONObject(); + if (AccessStatus.ALLOWED.equals(capabilityService.getCapabilityAccessState(nodeRef, + RMPermissionModel.VIEW_RECORDS)) == true) + { + // Indicate whether the node is a RM object or not + boolean isFilePlanComponent = recordsManagementService.isFilePlanComponent(nodeInfo.getNodeRef()); + rootJSONObject.put("isRmNode", isFilePlanComponent); - // UI convenience type - rmNodeValues.put("uiType", getUIType(nodeRef)); - - // Get the 'kind' of the file plan component - FilePlanComponentKind kind = recordsManagementService.getFilePlanComponentKind(nodeRef); - rmNodeValues.put("kind", kind.toString()); - - // File plan node reference - NodeRef filePlan = recordsManagementService.getFilePlan(nodeRef); - rmNodeValues.put("filePlan", filePlan.toString()); - - // Unfiled container node reference - NodeRef unfiledRecordContainer = recordService.getUnfiledContainer(filePlan); - if (unfiledRecordContainer != null) - { - rmNodeValues.put("unfiledRecordContainer", unfiledRecordContainer.toString()); - rmNodeValues.put("properties", propertiesToJSON(unfiledRecordContainer, useShortQName)); - QName type = fileFolderService.getFileInfo(unfiledRecordContainer).getType(); - rmNodeValues.put("type", useShortQName ? type.toPrefixString(namespaceService) : type.toString()); - } - - // Set the indicators array - setIndicators(rmNodeValues, nodeRef); - - // Set the actions array - setActions(rmNodeValues, nodeRef); - - return rmNodeValues; - } - - @SuppressWarnings("unchecked") - private void setIndicators(JSONObject rmNodeValues, NodeRef nodeRef) - { - if (indicators != null && indicators.isEmpty() == false) - { - JSONArray jsonIndicators = new JSONArray(); - - for (BaseEvaluator indicator : indicators) - { - if (indicator.evaluate(nodeRef) == true) + if (isFilePlanComponent == true) { - jsonIndicators.add(indicator.getName()); + rootJSONObject.put("rmNode", setRmNodeValues(nodeRef, rootJSONObject, useShortQNames)); } - } + } + } - rmNodeValues.put("indicators", jsonIndicators); - } - } + /** + * @param nodeRef + * @param rootJSONObject + * @param useShortQName + * @return + */ + @SuppressWarnings("unchecked") + private JSONObject setRmNodeValues(NodeRef nodeRef, JSONObject rootJSONObject, boolean useShortQName) + { + JSONObject rmNodeValues = new JSONObject(); - @SuppressWarnings("unchecked") - private void setActions(JSONObject rmNodeValues, NodeRef nodeRef) - { - if (actions != null && actions.isEmpty() == false) - { - JSONArray jsonActions = new JSONArray(); + // UI convenience type + rmNodeValues.put("uiType", getUIType(nodeRef)); - for (BaseEvaluator action : actions) - { - if (action.evaluate(nodeRef) == true) - { - jsonActions.add(action.getName()); - } - } + // Get the 'kind' of the file plan component + FilePlanComponentKind kind = recordsManagementService.getFilePlanComponentKind(nodeRef); + rmNodeValues.put("kind", kind.toString()); - rmNodeValues.put("actions", jsonActions); - } - } + // File plan node reference + NodeRef filePlan = recordsManagementService.getFilePlan(nodeRef); + rmNodeValues.put("filePlan", filePlan.toString()); - /** - * Gets the rm 'type' used as a UI convenience and compatibility flag. - */ - private String getUIType(NodeRef nodeRef) - { - String result = "unknown"; + // Unfiled container node reference + NodeRef unfiledRecordContainer = filePlanService.getUnfiledContainer(filePlan); + if (unfiledRecordContainer != null) + { + rmNodeValues.put("unfiledRecordContainer", unfiledRecordContainer.toString()); + rmNodeValues.put("properties", propertiesToJSON(unfiledRecordContainer, useShortQName)); + QName type = fileFolderService.getFileInfo(unfiledRecordContainer).getType(); + rmNodeValues.put("type", useShortQName ? type.toPrefixString(namespaceService) : type.toString()); + } - FilePlanComponentKind kind = recordsManagementService.getFilePlanComponentKind(nodeRef); - if (kind != null) - { - switch (kind) - { - case FILE_PLAN: - { - result = "fileplan"; - break; - } - case RECORD_CATEGORY: - { - result = "record-category"; - break; - } - case RECORD_FOLDER: - { - if (recordsManagementService.isMetadataStub(nodeRef) == true) - { - result = "metadata-stub-folder"; - } - else - { - result = "record-folder"; - } - break; - } - case RECORD: - { - if (recordsManagementService.isMetadataStub(nodeRef) == true) - { - result = "metadata-stub"; - } - else - { - if (recordService.isDeclared(nodeRef) == true) - { - result = "record"; - } - else - { - result = "undeclared-record"; - } - } - break; - } - case HOLD: - { - result = "hold-container"; - break; - } - case TRANSFER: - { - result = "transfer-container"; - break; - } - } - } + // Set the indicators array + setIndicators(rmNodeValues, nodeRef); - return result; - } + // Set the actions array + setActions(rmNodeValues, nodeRef); + + return rmNodeValues; + } + + @SuppressWarnings("unchecked") + private void setIndicators(JSONObject rmNodeValues, NodeRef nodeRef) + { + if (indicators != null && indicators.isEmpty() == false) + { + JSONArray jsonIndicators = new JSONArray(); + + for (BaseEvaluator indicator : indicators) + { + if (indicator.evaluate(nodeRef) == true) + { + jsonIndicators.add(indicator.getName()); + } + } + + rmNodeValues.put("indicators", jsonIndicators); + } + } + + @SuppressWarnings("unchecked") + private void setActions(JSONObject rmNodeValues, NodeRef nodeRef) + { + if (actions != null && actions.isEmpty() == false) + { + JSONArray jsonActions = new JSONArray(); + + for (BaseEvaluator action : actions) + { + if (action.evaluate(nodeRef) == true) + { + jsonActions.add(action.getName()); + } + } + + rmNodeValues.put("actions", jsonActions); + } + } + + /** + * Gets the rm 'type' used as a UI convenience and compatibility flag. + */ + private String getUIType(NodeRef nodeRef) + { + String result = "unknown"; + + FilePlanComponentKind kind = recordsManagementService.getFilePlanComponentKind(nodeRef); + if (kind != null) + { + switch (kind) + { + case FILE_PLAN: + { + result = "fileplan"; + break; + } + case RECORD_CATEGORY: + { + result = "record-category"; + break; + } + case RECORD_FOLDER: + { + if (recordsManagementService.isMetadataStub(nodeRef) == true) + { + result = "metadata-stub-folder"; + } + else + { + result = "record-folder"; + } + break; + } + case RECORD: + { + if (recordsManagementService.isMetadataStub(nodeRef) == true) + { + result = "metadata-stub"; + } + else + { + if (recordService.isDeclared(nodeRef) == true) + { + result = "record"; + } + else + { + result = "undeclared-record"; + } + } + break; + } + case HOLD: + { + result = "hold-container"; + break; + } + case TRANSFER: + { + result = "transfer-container"; + break; + } + } + } + + return result; + } } 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 9e4f2a9019..9e85feb13f 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 @@ -170,7 +170,6 @@ public interface RecordsManagementModel extends RecordsManagementCustomModel public static final QName ASPECT_RECORDS_MANAGEMENT_ROOT = QName.createQName(RM_URI, "recordsManagementRoot"); public static final QName ASSOC_HOLDS = QName.createQName(RM_URI, "holds"); public static final QName ASSOC_TRANSFERS = QName.createQName(RM_URI, "transfers"); - public static final QName ASSOC_UNFILED_RECORDS = QName.createQName(RM_URI, "unfiledRecords"); // Hold type public static final QName TYPE_HOLD = QName.createQName(RM_URI, "hold"); diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/patch/RMv21InPlacePatch.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/patch/RMv21InPlacePatch.java index 48549f6a51..1da75bfadf 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/patch/RMv21InPlacePatch.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/patch/RMv21InPlacePatch.java @@ -18,25 +18,18 @@ */ package org.alfresco.module.org_alfresco_module_rm.patch; -import java.io.Serializable; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import org.alfresco.model.ContentModel; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.dod5015.DOD5015Model; +import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; -import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService; -import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleServiceImpl; import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority; import org.alfresco.module.org_alfresco_module_rm.security.FilePlanPermissionService; import org.alfresco.repo.module.AbstractModuleComponent; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.namespace.QName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanNameAware; @@ -53,9 +46,6 @@ public class RMv21InPlacePatch extends AbstractModuleComponent /** Logger */ private static Log logger = LogFactory.getLog(RMv21InPlacePatch.class); - /** Node service */ - private NodeService nodeService; - /** Permission service */ private PermissionService permissionService; @@ -65,16 +55,8 @@ public class RMv21InPlacePatch extends AbstractModuleComponent /** File plan permission service */ private FilePlanPermissionService filePlanPermissionService; - /** File plan role service */ - private FilePlanRoleService filePlanRoleService; - - /** - * @param nodeService node service - */ - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } + /** File plan service */ + private FilePlanService filePlanService; /** * @param permissionService permission service @@ -101,11 +83,11 @@ public class RMv21InPlacePatch extends AbstractModuleComponent } /** - * @param filePlanRoleService file plan role service + * @param filePlanService file plan service */ - public void setFilePlanRoleService(FilePlanRoleService filePlanRoleService) + public void setFilePlanService(FilePlanService filePlanService) { - this.filePlanRoleService = filePlanRoleService; + this.filePlanService = filePlanService; } /** @@ -138,7 +120,7 @@ public class RMv21InPlacePatch extends AbstractModuleComponent permissionService.setPermission(filePlan, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.VIEW_RECORDS, true); // create unfiled container - createUnfiledContainer(filePlan); + filePlanService.createUnfiledContainer(filePlan); } if (logger.isDebugEnabled() == true) @@ -147,34 +129,5 @@ public class RMv21InPlacePatch extends AbstractModuleComponent } } - /** - * TODO .. this should really be moved to a service call ... should be on the FilPlanService? - */ - private NodeRef createUnfiledContainer(NodeRef filePlan) - { - String allRoles = filePlanRoleService.getAllRolesContainerGroup(filePlan); - - // create the properties map - Map properties = new HashMap(1); - properties.put(ContentModel.PROP_NAME, FilePlanRoleServiceImpl.NAME_UNFILED_CONTAINER); - - // create the unfiled container - NodeRef container = nodeService.createNode( - filePlan, - ASSOC_UNFILED_RECORDS, - QName.createQName(RM_URI, FilePlanRoleServiceImpl.NAME_UNFILED_CONTAINER), - TYPE_UNFILED_RECORD_CONTAINER, - properties).getChildRef(); - - // set inheritance to false - permissionService.setInheritParentPermissions(container, false); - permissionService.setPermission(container, allRoles, RMPermissionModel.READ_RECORDS, true); - permissionService.setPermission(container, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS, true); - - // TODO set the admin users to have filing permissions on the unfiled container!!! - // TODO we will need to be able to get a list of the admin roles from the service - - return container; - } } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java index 234b0f1ba4..13d3ee41ec 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java @@ -54,15 +54,6 @@ public interface RecordService * @return boolean true if record is declared, false otherwise */ boolean isDeclared(NodeRef nodeRef); - - // TODO move to filePlan service - /** - * Gets the unfiled root container for the given file plan - * - * @param filePlan The filePlan for which the unfiled record container should be retrieved - * @return NodeRef The nodeRef of the container object - */ - public NodeRef getUnfiledContainer(NodeRef filePlan); /** * Creates a new unfiled record from an existing node. diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java index 26e4b97264..a0e75b5b9a 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java @@ -23,7 +23,6 @@ import java.util.Calendar; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; @@ -32,14 +31,15 @@ import org.alfresco.model.ContentModel; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; 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.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.identifier.IdentifierService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService; import org.alfresco.module.org_alfresco_module_rm.vital.VitalRecordServiceImpl; import org.alfresco.repo.node.NodeServicePolicies; -import org.alfresco.repo.policy.Behaviour.NotificationFrequency; import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.PolicyComponent; +import org.alfresco.repo.policy.Behaviour.NotificationFrequency; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.permissions.AccessDeniedException; @@ -51,7 +51,6 @@ import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.QName; -import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.util.ParameterCheck; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; @@ -91,6 +90,9 @@ public class RecordServiceImpl implements RecordService, /** Disposition service */ private DispositionService dispositionService; + + /** File plan service */ + private FilePlanService filePlanService; /** Policy component */ private PolicyComponent policyComponent; @@ -165,6 +167,14 @@ public class RecordServiceImpl implements RecordService, { this.dispositionService = dispositionService; } + + /** + * @param filePlanService file plan service + */ + public void setFilePlanService(FilePlanService filePlanService) + { + this.filePlanService = filePlanService; + } /** * @param policyComponent policy component @@ -250,37 +260,6 @@ public class RecordServiceImpl implements RecordService, return nodeService.hasAspect(record, ASPECT_DECLARED_RECORD); } - - /** - * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#getUnfiledRootContainer(org.alfresco.service.cmr.repository.NodeRef) - */ - @Override - public NodeRef getUnfiledContainer(NodeRef filePlan) - { - ParameterCheck.mandatory("filePlan", filePlan); - - if (recordsManagementService.isFilePlan(filePlan) == false) - { - throw new AlfrescoRuntimeException("Unable to get the unfiled container, because passed node is not a file plan."); - } - - NodeRef result = null; - - List assocs = nodeService.getChildAssocs(filePlan, ASSOC_UNFILED_RECORDS, - RegexQNamePattern.MATCH_ALL); - if (assocs.size() > 1) - { - throw new AlfrescoRuntimeException( - "Unable to get the unfiled container, because the container cannot be indentified."); - } - else if (assocs.size() == 1 ) - { - result = assocs.get(0).getChildRef(); - } - - return result; - } - /** * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#createRecord(org.alfresco.service.cmr.repository.NodeRef, * org.alfresco.service.cmr.repository.NodeRef) @@ -310,7 +289,7 @@ public class RecordServiceImpl implements RecordService, public Void doWork() throws Exception { // get the new record container for the file plan - NodeRef newRecordContainer = getUnfiledContainer(filePlan); + NodeRef newRecordContainer = filePlanService.getUnfiledContainer(filePlan); if (newRecordContainer == null) { throw new AlfrescoRuntimeException("Unable to create record, because new record container could not be found."); diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/recordfolder/RecordFolderService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/recordfolder/RecordFolderService.java index 9ed54bdf32..6c14447246 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/recordfolder/RecordFolderService.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/recordfolder/RecordFolderService.java @@ -21,6 +21,8 @@ package org.alfresco.module.org_alfresco_module_rm.recordfolder; /** * Record folder service interface * + * TODO move methods from RecordManagementService + * * @author Roy Wetherall * @since 2.1 */ diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java index e5913077fb..2ac5040df9 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java @@ -22,19 +22,15 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.Serializable; -import java.util.HashMap; import java.util.HashSet; -import java.util.Map; import java.util.Set; import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.model.ContentModel; 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.capability.RMPermissionModel; +import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; -import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority; import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.policy.JavaBehaviour; @@ -49,7 +45,6 @@ import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.AuthorityType; import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.namespace.QName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONArray; @@ -77,8 +72,8 @@ public class FilePlanRoleServiceImpl implements FilePlanRoleService, /** Policy component */ private PolicyComponent policyComponent; - /** Record service */ - private RecordService recordService; + /** File plan service */ + private FilePlanService filePlanService; /** Node service */ private NodeService nodeService; @@ -86,9 +81,6 @@ public class FilePlanRoleServiceImpl implements FilePlanRoleService, /** Records management role zone */ public static final String RM_ROLE_ZONE_PREFIX = "rmRoleZone"; - /** Unfiled record container name */ - public static final String NAME_UNFILED_CONTAINER = "Unfiled Records"; - /** Logger */ private static Log logger = LogFactory.getLog(FilePlanRoleServiceImpl.class); @@ -133,11 +125,11 @@ public class FilePlanRoleServiceImpl implements FilePlanRoleService, } /** - * @param recordService record service + * @param filePlanService file plan service */ - public void setRecordService(RecordService recordService) + public void setFilePlanService(FilePlanService filePlanService) { - this.recordService = recordService; + this.filePlanService = filePlanService; } /** @@ -187,7 +179,7 @@ public class FilePlanRoleServiceImpl implements FilePlanRoleService, permissionService.setPermission(rmRootNode, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.VIEW_RECORDS, true); // Create the unfiled record container - return createUnfiledContainer(rmRootNode, allRoles); + return filePlanService.createUnfiledContainer(rmRootNode); } }, AuthenticationUtil.getSystemUserName()); @@ -196,39 +188,6 @@ public class FilePlanRoleServiceImpl implements FilePlanRoleService, } } - /** - * Creates unfiled container node and sets up permissions - * - * @param rmRootNode - * @param allRoles - */ - private NodeRef createUnfiledContainer(NodeRef rmRootNode, String allRoles) - { - NodeRef container = recordService.getUnfiledContainer(rmRootNode); - - if (container == null) - { - // create the properties map - Map properties = new HashMap(1); - properties.put(ContentModel.PROP_NAME, NAME_UNFILED_CONTAINER); - - // create the unfiled container - container = nodeService.createNode( - rmRootNode, - ASSOC_UNFILED_RECORDS, - QName.createQName(RM_URI, NAME_UNFILED_CONTAINER), - TYPE_UNFILED_RECORD_CONTAINER, - properties).getChildRef(); - - // set inheritance to false - permissionService.setInheritParentPermissions(container, false); - permissionService.setPermission(container, allRoles, RMPermissionModel.READ_RECORDS, true); - permissionService.setPermission(container, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS, true); - } - - return container; - } - /** * Delete root node behaviour * diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordServiceImplTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordServiceImplTest.java index 408d29824c..498b1875d5 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordServiceImplTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordServiceImplTest.java @@ -359,21 +359,4 @@ public class RecordServiceImplTest extends BaseRMTestCase assertEquals(recordExpected, dmPermissionService.hasPermission(dmDocument, permission)); } - - /** - * @see RecordService#getUnfiledContainer(org.alfresco.service.cmr.repository.NodeRef) - */ - public void testGetUnfiledContainer() throws Exception - { - doTestInTransaction(new Test() - { - @Override - public Void run() - { - assertNotNull(recordService.getUnfiledContainer(filePlan)); - - 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 e002c271d2..e58145370a 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 @@ -32,6 +32,7 @@ import org.alfresco.module.org_alfresco_module_rm.dataset.DataSetService; 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.RecordsManagementEventService; +import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.model.behaviour.RmSiteType; @@ -130,6 +131,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase protected DataSetService dataSetService; protected FreezeService freezeService; protected RecordService recordService; + protected FilePlanService filePlanService; /** test data */ protected StoreRef storeRef; @@ -347,6 +349,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase dataSetService = (DataSetService) applicationContext.getBean("DataSetService"); freezeService = (FreezeService) applicationContext.getBean("FreezeService"); recordService = (RecordService) applicationContext.getBean("RecordService"); + filePlanService = (FilePlanService) applicationContext.getBean("FilePlanService"); } /** @@ -427,7 +430,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase utils.declareRecord(recordDeclaredTwo); // unfiled container - unfiledContainer = recordService.getUnfiledContainer(filePlan); + unfiledContainer = filePlanService.getUnfiledContainer(filePlan); assertNotNull(unfiledContainer); } }