From 4f95c905a64a927c9c66aa3a7a23c79ac073b9a0 Mon Sep 17 00:00:00 2001 From: Ana Bozianu Date: Sat, 17 Dec 2016 23:22:12 +0200 Subject: [PATCH] RM-4436 - implemented file record RM-4429 - implemented declare record -renamed the nodes package into fileplancomponents --- .../rm-public-rest-context.xml | 35 +++- .../org/alfresco/rm/rest/api/RMNodes.java | 13 ++ .../org/alfresco/rm/rest/api/Records.java | 63 ++++++ .../FileplanComponentChildrenRelation.java | 2 +- .../FileplanComponentsEntityResource.java | 2 +- .../api/fileplancomponents/package-info.java | 37 ++++ .../rest/api/files/FilesEntityResource.java | 69 ++++++ .../api/{nodes => files}/package-info.java | 4 +- .../rm/rest/api/impl/RMNodesImpl.java | 37 ++-- .../rm/rest/api/impl/RecordsImpl.java | 198 ++++++++++++++++++ .../rm/rest/api/model/TargetContainer.java | 74 +++++++ .../RecordsEntityResource.java | 52 +++-- .../rm/rest/api/records/package-info.java | 37 ++++ ...planComponentChildrenRelationUnitTest.java | 2 +- ...eplanComponentsEntityResourceUnitTest.java | 2 +- .../impl/RMNodesImplRelativePathUnitTest.java | 22 +- 16 files changed, 576 insertions(+), 73 deletions(-) create mode 100644 rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/Records.java rename rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/{nodes => fileplancomponents}/FileplanComponentChildrenRelation.java (98%) rename rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/{nodes => fileplancomponents}/FileplanComponentsEntityResource.java (98%) create mode 100644 rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/fileplancomponents/package-info.java create mode 100644 rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/files/FilesEntityResource.java rename rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/{nodes => files}/package-info.java (92%) create mode 100644 rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/RecordsImpl.java create mode 100644 rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/model/TargetContainer.java rename rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/{nodes => records}/RecordsEntityResource.java (71%) create mode 100644 rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/records/package-info.java rename rm-community/rm-community-repo/unit-test/java/org/alfresco/rm/rest/api/{nodes => fileplancomponents}/FileplanComponentChildrenRelationUnitTest.java (98%) rename rm-community/rm-community-repo/unit-test/java/org/alfresco/rm/rest/api/{nodes => fileplancomponents}/FileplanComponentsEntityResourceUnitTest.java (98%) diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-public-rest-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-public-rest-context.xml index f4e068dc03..71db247827 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-public-rest-context.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-public-rest-context.xml @@ -45,18 +45,23 @@ - + - + - + + + + + + @@ -84,6 +89,30 @@ + + + + + + + + + + + + + org.alfresco.rm.rest.api.Records + + + + + + + + + + + diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/RMNodes.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/RMNodes.java index 983f985e96..e56e5ad748 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/RMNodes.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/RMNodes.java @@ -28,6 +28,8 @@ package org.alfresco.rm.rest.api; import org.alfresco.rest.api.Nodes; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; /** * RM Nodes API @@ -45,4 +47,15 @@ public interface RMNodes extends Nodes public static String PARAM_INCLUDE_HAS_RETENTION_SCHEDULE = "hasRetentionSchedule"; public static String PARAM_INCLUDE_IS_CLOSED = "isClosed"; public static String PARAM_INCLUDE_IS_COMPLETED = "isCompleted"; + + /** + * Gets or creates the relative path starting from the provided parent folder. + * The method decides the type of the created elements considering the + * parent container's type and the type of the node to be created. + * @param parentFolderNodeId the parent folder to start from + * @param relativePath the relative path + * @param nodeTypeQName the type of the node to be created + * @return reference to the last element of the created path + */ + public NodeRef getOrCreatePath(String parentFolderNodeId, String relativePath, QName nodeTypeQName); } diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/Records.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/Records.java new file mode 100644 index 0000000000..504b81309b --- /dev/null +++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/Records.java @@ -0,0 +1,63 @@ +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * - + * 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 . + * #L% + */ + +package org.alfresco.rm.rest.api; + +import org.alfresco.rest.api.model.Node; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.rm.rest.api.model.TargetContainer; + +/** + * Records API + * + * @author Ana Bozianu + * @since 2.6 + */ +public interface Records +{ + public static final String PARAM_HIDE_RECORD = "hideRecord"; + + /** + * Creates a record from a file + * + * @param fileId the id of a non record file + * @param parameters the {@link Parameters} object to get the parameters passed into the request + * @return information about the created record + */ + public Node declareFileAsRecord(String fileId, Parameters parameters); + + /** + * Files a record into th fileplan. + * If the record is already filed it links the record to the target folder + * + * @param recordId the id of the record do file/link + * @param target the target parent folder + * @param parameters the {@link Parameters} object to get the parameters passed into the request + * @return information about the new state of the record + */ + public Node fileOrLinkRecord(String recordId, TargetContainer target, Parameters parameters); +} diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/nodes/FileplanComponentChildrenRelation.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/fileplancomponents/FileplanComponentChildrenRelation.java similarity index 98% rename from rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/nodes/FileplanComponentChildrenRelation.java rename to rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/fileplancomponents/FileplanComponentChildrenRelation.java index 5c16af45ab..19a61aaf3f 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/nodes/FileplanComponentChildrenRelation.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/fileplancomponents/FileplanComponentChildrenRelation.java @@ -25,7 +25,7 @@ * #L% */ -package org.alfresco.rm.rest.api.nodes; +package org.alfresco.rm.rest.api.fileplancomponents; import java.util.ArrayList; import java.util.List; diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/nodes/FileplanComponentsEntityResource.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/fileplancomponents/FileplanComponentsEntityResource.java similarity index 98% rename from rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/nodes/FileplanComponentsEntityResource.java rename to rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/fileplancomponents/FileplanComponentsEntityResource.java index e0d6c8c360..648455f613 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/nodes/FileplanComponentsEntityResource.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/fileplancomponents/FileplanComponentsEntityResource.java @@ -25,7 +25,7 @@ * #L% */ -package org.alfresco.rm.rest.api.nodes; +package org.alfresco.rm.rest.api.fileplancomponents; import org.alfresco.rest.api.model.Node; import org.alfresco.rest.framework.WebApiDescription; diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/fileplancomponents/package-info.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/fileplancomponents/package-info.java new file mode 100644 index 0000000000..f4ef3b5150 --- /dev/null +++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/fileplancomponents/package-info.java @@ -0,0 +1,37 @@ +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * - + * 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 . + * #L% + */ + +/** + * Package info that defines the Information Governance Fileplan Components REST API + * + * @author Ana Bozianu + * @since 2.6 + */ +@WebApi(name="ig", scope=Api.SCOPE.PUBLIC, version=1) +package org.alfresco.rm.rest.api.fileplancomponents; +import org.alfresco.rest.framework.Api; +import org.alfresco.rest.framework.WebApi; \ No newline at end of file diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/files/FilesEntityResource.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/files/FilesEntityResource.java new file mode 100644 index 0000000000..718d7cc592 --- /dev/null +++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/files/FilesEntityResource.java @@ -0,0 +1,69 @@ +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * - + * 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 . + * #L% + */ + +package org.alfresco.rm.rest.api.files; + +import org.alfresco.rest.api.model.Node; +import org.alfresco.rest.framework.Operation; +import org.alfresco.rest.framework.WebApiDescription; +import org.alfresco.rest.framework.resource.EntityResource; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.rest.framework.webscripts.WithResponse; +import org.alfresco.rm.rest.api.Records; +import org.alfresco.rm.rest.api.model.TargetContainer; +import org.alfresco.util.ParameterCheck; +import org.springframework.beans.factory.InitializingBean; + +/** + * An implementation of an Entity Resource for a file + * + * @author Ana Bozianu + * @since 2.6 + */ +@EntityResource(name="files", title = "Files") +public class FilesEntityResource implements InitializingBean +{ + private Records records; + + public void setRecords(Records records) + { + this.records = records; + } + + @Operation("declare") + @WebApiDescription(title = "Declare as record", description="Declare a file as record.") + public Node declareAsRecord(String fileId, Void body, Parameters parameters, WithResponse withResponse) + { + return records.declareFileAsRecord(fileId, parameters); + } + + @Override + public void afterPropertiesSet() throws Exception + { + ParameterCheck.mandatory("records", this.records); + } +} diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/nodes/package-info.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/files/package-info.java similarity index 92% rename from rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/nodes/package-info.java rename to rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/files/package-info.java index e8f77618fc..8ba4b1f926 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/nodes/package-info.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/files/package-info.java @@ -26,12 +26,12 @@ */ /** - * Package info that defines the Information Governance Nodes REST API + * Package info that defines the Information Governance Files REST API * * @author Ana Bozianu * @since 2.6 */ @WebApi(name="ig", scope=Api.SCOPE.PUBLIC, version=1) -package org.alfresco.rm.rest.api.nodes; +package org.alfresco.rm.rest.api.files; import org.alfresco.rest.framework.Api; import org.alfresco.rest.framework.WebApi; \ No newline at end of file diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/RMNodesImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/RMNodesImpl.java index 2c5b3d28eb..f10aa6e7a1 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/RMNodesImpl.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/RMNodesImpl.java @@ -336,25 +336,30 @@ public class RMNodesImpl extends NodesImpl implements RMNodes public Node createNode(String parentFolderNodeId, Node nodeInfo, Parameters parameters) { // create RM path if needed and call the super method with the last element of the created path - NodeRef parentNodeRef = getOrCreatePath(parentFolderNodeId, nodeInfo); + String relativePath = nodeInfo.getRelativePath(); + + // Get the type of the node to be created + String nodeType = nodeInfo.getNodeType(); + if ((nodeType == null) || nodeType.isEmpty()) + { + throw new InvalidArgumentException("Node type is expected: "+parentFolderNodeId+","+nodeInfo.getName()); + } + QName nodeTypeQName = createQName(nodeType); + + // Get or create the path + NodeRef parentNodeRef = getOrCreatePath(parentFolderNodeId, relativePath, nodeTypeQName); + + // Set relative path to null as we pass the last element from the path nodeInfo.setRelativePath(null); return super.createNode(parentNodeRef.getId(), nodeInfo, parameters); } - /** - * Gets or creates the relative path specified in nodeInfo.relativePath - * starting from the provided parent folder. - * The method decides the type of the created elements considering the - * parent container's type and the type of the node to be created. - * @param parentFolderNodeId the parent folder to start from - * @param nodeInfo information about the node to be created - * @return reference to the last element of the created path - */ - protected NodeRef getOrCreatePath(String parentFolderNodeId, Node nodeInfo) + @Override + public NodeRef getOrCreatePath(String parentFolderNodeId, String relativePath, QName nodeTypeQName) { NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, null); - String relativePath = nodeInfo.getRelativePath(); + if (relativePath == null) { return parentNodeRef; @@ -413,14 +418,6 @@ public class RMNodesImpl extends NodesImpl implements RMNodes } else { - // Get the type of the node to be created - String nodeType = nodeInfo.getNodeType(); - if ((nodeType == null) || nodeType.isEmpty()) - { - throw new InvalidArgumentException("Node type is expected: "+parentFolderNodeId+","+nodeInfo.getName()); - } - QName nodeTypeQName = createQName(nodeType); - /* Outside the unfiled record container the path elements are record categories * except the last element which is a record folder if the created node is of type content */ diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/RecordsImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/RecordsImpl.java new file mode 100644 index 0000000000..357fa47a53 --- /dev/null +++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/RecordsImpl.java @@ -0,0 +1,198 @@ +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * - + * 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 . + * #L% + */ + +package org.alfresco.rm.rest.api.impl; + +import java.security.InvalidParameterException; + +import org.alfresco.model.ContentModel; +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.repo.node.integrity.IntegrityException; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.rest.api.model.Node; +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.rm.rest.api.RMNodes; +import org.alfresco.rm.rest.api.Records; +import org.alfresco.rm.rest.api.model.TargetContainer; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.model.FileExistsException; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.model.FileNotFoundException; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.dao.ConcurrencyFailureException; +import org.springframework.extensions.surf.util.ParameterCheck; + +public class RecordsImpl implements Records, InitializingBean +{ + protected RecordService recordService; + protected FilePlanService filePlanService; + protected NodeService nodeService; + protected FileFolderService fileFolderService; + protected DictionaryService dictionaryService; + protected RMNodes nodes; + + public void setRecordService(RecordService recordService) + { + this.recordService = recordService; + } + + public void setFilePlanService(FilePlanService filePlanService) + { + this.filePlanService = filePlanService; + } + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setFileFolderService(FileFolderService fileFolderService) + { + this.fileFolderService = fileFolderService; + } + + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + public void setNodes(RMNodes nodes) + { + this.nodes = nodes; + } + + @Override + public Node declareFileAsRecord(String fileId, Parameters parameters) + { + // Parameter check + if ((fileId == null) || (fileId.isEmpty())) + { + throw new InvalidArgumentException("Missing fileId"); + } + + // Get file to be declared + NodeRef fileNodeRef = nodes.validateNode(fileId) ; + + // Get fileplan + NodeRef filePlan = AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public NodeRef doWork() + { + return filePlanService.getFilePlanBySiteId(FilePlanService.DEFAULT_RM_SITE_ID); + } + }); + + // default false (if not provided) + boolean hideRecord = Boolean.valueOf(parameters.getParameter(PARAM_HIDE_RECORD)); + + // Create the record + recordService.createRecord(filePlan, fileNodeRef, !hideRecord); + + // Get information about the new record + return nodes.getFolderOrDocument(fileId, parameters); + } + + @Override + public Node fileOrLinkRecord(String recordId, TargetContainer target, Parameters parameters) + { + ParameterCheck.mandatoryString("recordId", recordId); + + if((target.getTargetParentId() == null || target.getTargetParentId().isEmpty()) && + (target.getRelativePath() == null || target.getRelativePath().isEmpty())) + { + throw new InvalidParameterException("No target folder information was provided"); + } + + // Get record + NodeRef record = nodes.validateNode(recordId); + + // Get record folder to file/link the record to + String parentContainerId = target.getTargetParentId(); + if(parentContainerId == null || parentContainerId.isEmpty()) + { + // If target container not provided get fileplan + parentContainerId = AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public String doWork() + { + return filePlanService.getFilePlanBySiteId(FilePlanService.DEFAULT_RM_SITE_ID).getId(); + } + }); + } + NodeRef parentRecordFolder = nodes.getOrCreatePath(parentContainerId, target.getRelativePath(), ContentModel.TYPE_CONTENT); + + // Check if the target is a record folder + if(!dictionaryService.isSubClass(nodeService.getType(parentRecordFolder), RecordsManagementModel.TYPE_RECORD_FOLDER)) + { + throw new InvalidArgumentException("The provided target parent is not a record folder"); + } + + // Get the current parent type to decide if we link or move the record + NodeRef primaryParent = nodeService.getPrimaryParent(record).getParentRef(); + if(dictionaryService.isSubClass(nodeService.getType(primaryParent), RecordsManagementModel.TYPE_RECORD_FOLDER)) + { + recordService.link(record, parentRecordFolder); + } + else + { + try + { + fileFolderService.moveFrom(record, primaryParent, parentRecordFolder, null); + } + catch (FileExistsException e) + { + throw new IntegrityException(e.getMessage(), null); + } + catch (FileNotFoundException e) + { + throw new ConcurrencyFailureException("The record was deleted while filing it", e); + } + } + + // Get the record info + return nodes.getFolderOrDocument(recordId, parameters); + } + + @Override + public void afterPropertiesSet() throws Exception + { + ParameterCheck.mandatory("recordService", recordService); + ParameterCheck.mandatory("filePlanService", filePlanService); + ParameterCheck.mandatory("nodes", nodes); + ParameterCheck.mandatory("nodeService", nodeService); + ParameterCheck.mandatory("fileFolderService", fileFolderService); + ParameterCheck.mandatory("dictionaryService", dictionaryService); + } +} diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/model/TargetContainer.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/model/TargetContainer.java new file mode 100644 index 0000000000..4607aab5d6 --- /dev/null +++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/model/TargetContainer.java @@ -0,0 +1,74 @@ +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * - + * 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 . + * #L% + */ + +package org.alfresco.rm.rest.api.model; + +/** + * A target container object + * + * @author Ana Bozianu + * @since 2.6 + */ +public class TargetContainer +{ + String targetParentId; + String relativePath; + + public TargetContainer() + { + } + + public String getTargetParentId() + { + return targetParentId; + } + + public void setTargetParentId(String targetParentId) + { + this.targetParentId = targetParentId; + } + + public String getRelativePath() + { + return relativePath; + } + + public void setRelativePath(String relativePath) + { + this.relativePath = relativePath; + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder("NodeTarget{"); + sb.append("targetParentId=").append(targetParentId); + sb.append(", relativePath='").append(relativePath).append('\''); + sb.append('}'); + return sb.toString(); + } +} diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/nodes/RecordsEntityResource.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/records/RecordsEntityResource.java similarity index 71% rename from rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/nodes/RecordsEntityResource.java rename to rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/records/RecordsEntityResource.java index 215a43f49a..85e216de59 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/nodes/RecordsEntityResource.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/records/RecordsEntityResource.java @@ -25,20 +25,21 @@ * #L% */ -package org.alfresco.rm.rest.api.nodes; - -import java.io.InputStream; +package org.alfresco.rm.rest.api.records; import org.alfresco.rest.api.model.Node; import org.alfresco.rest.framework.BinaryProperties; +import org.alfresco.rest.framework.Operation; import org.alfresco.rest.framework.WebApiDescription; import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; import org.alfresco.rest.framework.resource.EntityResource; import org.alfresco.rest.framework.resource.actions.interfaces.BinaryResourceAction; -import org.alfresco.rest.framework.resource.content.BasicContentInfo; import org.alfresco.rest.framework.resource.content.BinaryResource; import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.rest.framework.webscripts.WithResponse; import org.alfresco.rm.rest.api.RMNodes; +import org.alfresco.rm.rest.api.Records; +import org.alfresco.rm.rest.api.model.TargetContainer; import org.alfresco.util.ParameterCheck; import org.springframework.beans.factory.InitializingBean; @@ -49,22 +50,21 @@ import org.springframework.beans.factory.InitializingBean; * @since 2.6 */ @EntityResource(name="records", title = "Records") -public class RecordsEntityResource implements BinaryResourceAction.Update, - BinaryResourceAction.Read, +public class RecordsEntityResource implements BinaryResourceAction.Read, InitializingBean { private RMNodes nodes; + private Records records; public void setNodes(RMNodes nodes) { this.nodes = nodes; } - @Override - public void afterPropertiesSet() throws Exception + public void setRecords(Records records) { - ParameterCheck.mandatory("nodes", this.nodes); + this.records = records; } /** @@ -83,24 +83,22 @@ public class RecordsEntityResource implements BinaryResourceAction.Update, return nodes.getContent(recordId, parameters, true); } - /** - * Upload new version of content - * - * This allow binary content update of an existing record. - * - * Note: alternatively, can upload via POST (multipart/form-data) with existing file name and form "overwrite=true". - * - * @param recordId the id of the record to set the content for - * @param contentInfo Basic information about the content stream - * @param stream an inputstream representing the new content of the node - * @param parameters {@link Parameters} - * @return information about the record that has been updated - */ - @Override - @WebApiDescription(title = "Upload content", description = "Upload content") - @BinaryProperties({"content"}) - public Node updateProperty(String recordId, BasicContentInfo contentInfo, InputStream stream, Parameters parameters) + @Operation("file") + @WebApiDescription(title = "File record", description="File a record into fileplan.") + public Node fileRecord(String recordId, TargetContainer target, Parameters parameters, WithResponse withResponse) { - return nodes.updateContent(recordId, contentInfo, stream, parameters); + try{ + return records.fileOrLinkRecord(recordId, target, parameters); + }catch(Exception ex) + { + throw ex; + } + } + + @Override + public void afterPropertiesSet() throws Exception + { + ParameterCheck.mandatory("nodes", this.nodes); + ParameterCheck.mandatory("records", this.records); } } diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/records/package-info.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/records/package-info.java new file mode 100644 index 0000000000..0eaaf894a5 --- /dev/null +++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/records/package-info.java @@ -0,0 +1,37 @@ +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * - + * 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 . + * #L% + */ + +/** + * Package info that defines the Information Governance Records REST API + * + * @author Ana Bozianu + * @since 2.6 + */ +@WebApi(name="ig", scope=Api.SCOPE.PUBLIC, version=1) +package org.alfresco.rm.rest.api.records; +import org.alfresco.rest.framework.Api; +import org.alfresco.rest.framework.WebApi; \ No newline at end of file diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/rm/rest/api/nodes/FileplanComponentChildrenRelationUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/rm/rest/api/fileplancomponents/FileplanComponentChildrenRelationUnitTest.java similarity index 98% rename from rm-community/rm-community-repo/unit-test/java/org/alfresco/rm/rest/api/nodes/FileplanComponentChildrenRelationUnitTest.java rename to rm-community/rm-community-repo/unit-test/java/org/alfresco/rm/rest/api/fileplancomponents/FileplanComponentChildrenRelationUnitTest.java index 7e9c9d75e2..d4d48ad1c9 100644 --- a/rm-community/rm-community-repo/unit-test/java/org/alfresco/rm/rest/api/nodes/FileplanComponentChildrenRelationUnitTest.java +++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/rm/rest/api/fileplancomponents/FileplanComponentChildrenRelationUnitTest.java @@ -25,7 +25,7 @@ * #L% */ -package org.alfresco.rm.rest.api.nodes; +package org.alfresco.rm.rest.api.fileplancomponents; import static org.mockito.Mockito.mock; diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/rm/rest/api/nodes/FileplanComponentsEntityResourceUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/rm/rest/api/fileplancomponents/FileplanComponentsEntityResourceUnitTest.java similarity index 98% rename from rm-community/rm-community-repo/unit-test/java/org/alfresco/rm/rest/api/nodes/FileplanComponentsEntityResourceUnitTest.java rename to rm-community/rm-community-repo/unit-test/java/org/alfresco/rm/rest/api/fileplancomponents/FileplanComponentsEntityResourceUnitTest.java index 2a36bf6f1a..e2eed2a6f9 100644 --- a/rm-community/rm-community-repo/unit-test/java/org/alfresco/rm/rest/api/nodes/FileplanComponentsEntityResourceUnitTest.java +++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/rm/rest/api/fileplancomponents/FileplanComponentsEntityResourceUnitTest.java @@ -25,7 +25,7 @@ * #L% */ -package org.alfresco.rm.rest.api.nodes; +package org.alfresco.rm.rest.api.fileplancomponents; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/rm/rest/api/impl/RMNodesImplRelativePathUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/rm/rest/api/impl/RMNodesImplRelativePathUnitTest.java index cf25349247..bde808f728 100644 --- a/rm-community/rm-community-repo/unit-test/java/org/alfresco/rm/rest/api/impl/RMNodesImplRelativePathUnitTest.java +++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/rm/rest/api/impl/RMNodesImplRelativePathUnitTest.java @@ -90,8 +90,7 @@ public class RMNodesImplRelativePathUnitTest extends BaseUnitTest * When trying to create a node in the parent node with no relative path */ Node nodeInfo = mock(Node.class); - when(nodeInfo.getRelativePath()).thenReturn(null); - NodeRef returnedPath = rmNodesImpl.getOrCreatePath(parentNode.getId(), nodeInfo); + NodeRef returnedPath = rmNodesImpl.getOrCreatePath(parentNode.getId(), null, ContentModel.TYPE_CONTENT); /* * Then the parent node is returned and no node is created @@ -126,8 +125,7 @@ public class RMNodesImplRelativePathUnitTest extends BaseUnitTest * When trying to create a node in the parent node with the relative path c1/f1 */ Node nodeInfo = mock(Node.class); - when(nodeInfo.getRelativePath()).thenReturn(category + "/" + recordFolder); - NodeRef returnedPath = rmNodesImpl.getOrCreatePath(parentNode.getId(), nodeInfo); + NodeRef returnedPath = rmNodesImpl.getOrCreatePath(parentNode.getId(), category + "/" + recordFolder, ContentModel.TYPE_CONTENT); /* * Then the node f1 is returned and no node is created @@ -166,9 +164,6 @@ public class RMNodesImplRelativePathUnitTest extends BaseUnitTest /* * When trying to create a content node in the relative path c1/c2/c3/f1 */ - Node nodeInfo = mock(Node.class); - when(nodeInfo.getNodeType()).thenReturn("cm:content"); - // c3 String category3 = "c3"; NodeRef categoryNode3 = AlfMock.generateNodeRef(mockedNodeService); @@ -182,8 +177,7 @@ public class RMNodesImplRelativePathUnitTest extends BaseUnitTest when(mockedFileFolderService.create(categoryNode3, recordFolder, RecordsManagementModel.TYPE_RECORD_FOLDER)).thenReturn(recordFolderFileInfo); // call the class under tests - when(nodeInfo.getRelativePath()).thenReturn(category1 + "/" + category2 + "/" + category3 + "/" + recordFolder); - NodeRef returnedPath = rmNodesImpl.getOrCreatePath(fileplanNodeRef.getId(), nodeInfo); + NodeRef returnedPath = rmNodesImpl.getOrCreatePath(fileplanNodeRef.getId(), category1 + "/" + category2 + "/" + category3 + "/" + recordFolder, ContentModel.TYPE_CONTENT); /* * Then the category c1 and the record folder f1 should be created and f1 should be returned @@ -232,9 +226,7 @@ public class RMNodesImplRelativePathUnitTest extends BaseUnitTest when(mockedFileFolderService.create(folderNode2, folder3, RecordsManagementModel.TYPE_UNFILED_RECORD_FOLDER)).thenReturn(folderFileInfo3); // call the class under tests - Node nodeInfo = mock(Node.class); - when(nodeInfo.getRelativePath()).thenReturn(folder1 + "/" + folder2 + "/" + folder3); - NodeRef returnedParentNode = rmNodesImpl.getOrCreatePath(unfiledRecordContainer.getId(), nodeInfo); + NodeRef returnedParentNode = rmNodesImpl.getOrCreatePath(unfiledRecordContainer.getId(), folder1 + "/" + folder2 + "/" + folder3, ContentModel.TYPE_CONTENT); /* * Then the category c1 and the record folder rf1 should be created @@ -267,9 +259,6 @@ public class RMNodesImplRelativePathUnitTest extends BaseUnitTest /* * When trying to create a folder node in the relative path c1/c2/c3 */ - Node nodeInfo = mock(Node.class); - when(nodeInfo.getNodeType()).thenReturn("rma:recordFolder"); - // c1 String category1 = "c1"; NodeRef categoryNode1 = AlfMock.generateNodeRef(mockedNodeService); @@ -286,8 +275,7 @@ public class RMNodesImplRelativePathUnitTest extends BaseUnitTest when(mockedFilePlanService.createRecordCategory(categoryNode2, category3)).thenReturn(categoryNode3); // call the class under tests - when(nodeInfo.getRelativePath()).thenReturn(category1 + "/" + category2 + "/" + category3); - NodeRef returnedParentNode = rmNodesImpl.getOrCreatePath(fileplanNodeRef.getId(), nodeInfo); + NodeRef returnedParentNode = rmNodesImpl.getOrCreatePath(fileplanNodeRef.getId(), category1 + "/" + category2 + "/" + category3, RecordsManagementModel.TYPE_RECORD_FOLDER); /* * Then the categories c1, c2 and c3 should be created and c3 should be returned