diff --git a/README.txt b/README.txt
index f31803686a..b46013c3f5 100644
--- a/README.txt
+++ b/README.txt
@@ -95,9 +95,6 @@ Follow these instructions install licence and Outlook plugin:
- http://docs.alfresco.com/outlook2.1/tasks/Outlook-install_v2.html
-
-
-
SNAPSHOT dependencies:
----------------------
@@ -114,6 +111,7 @@ Code Formatting:
This project follows the usual Alfresco Coding Standards. If you use Eclipse or IntelliJ, there are settings inside the ide-config directory for you to import.
+
Surf build errors:
------------------
@@ -121,3 +119,11 @@ If you get:
[ERROR] Failed to execute goal on project alfresco-rm-community-share: Could not resolve dependencies for project org.alfresco:alfresco-rm-community-share:amp:2.6-SNAPSHOT: Failed to collect dependencies at org.alfresco.surf:spring-surf-api:jar:6.3 -> org.alfresco.surf:spring-surf:jar:${dependency.surf.version}: Failed to read artifact descriptor for org.alfresco.surf:spring-surf:jar:${dependency.surf.version}: Could not transfer artifact org.alfresco.surf:spring-surf:pom:${dependency.surf.version} from/to alfresco-internal (https://artifacts.alfresco.com/nexus/content/groups/private): Not authorized , ReasonPhrase:Unauthorized. -> [Help 1]
then please re-run with -Ddependency.surf.version=6.3
+
+
+Install lombok plugin for IDEs:
+-------------------------------
+
+To allow automation and benchmark projects to be built within an IDE the lombok 'plugin' needs to be installed.
+
+Execute lombok.jar (doubleclick it, or run java -jar lombok.jar). Follow instructions.
diff --git a/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/recordcategory/RecordCategoryChildProperties.java b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/recordcategory/RecordCategoryChildProperties.java
index 67e87511b4..abc4534aad 100644
--- a/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/recordcategory/RecordCategoryChildProperties.java
+++ b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/recordcategory/RecordCategoryChildProperties.java
@@ -134,7 +134,7 @@ public class RecordCategoryChildProperties extends TestModel
private Boolean recordSearchDispositionEventsEligible;
@JsonProperty (PROPERTIES_RECORD_SEARCH_DISPOSITION_INSTRUCTIONS)
- private String recordSearchDispositionInstructions;
+ private String recordSearchDispositionInstructions;
@JsonProperty (PROPERTIES_OWNER)
private Owner owner;
diff --git a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/recordcategories/RecordCategoryTests.java b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/recordcategories/RecordCategoryTests.java
index 92d1073588..b769d3d572 100644
--- a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/recordcategories/RecordCategoryTests.java
+++ b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/recordcategories/RecordCategoryTests.java
@@ -52,6 +52,7 @@ import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.NoSuchElementException;
@@ -66,7 +67,10 @@ import org.alfresco.rest.rm.community.model.recordfolder.RecordFolder;
import org.alfresco.rest.rm.community.requests.gscore.api.FilePlanAPI;
import org.alfresco.rest.rm.community.requests.gscore.api.RecordCategoryAPI;
import org.alfresco.rest.rm.community.requests.gscore.api.RecordFolderAPI;
+import org.alfresco.rest.v0.RecordCategoriesAPI;
+import org.alfresco.rest.core.v0.BaseAPI.RETENTION_SCHEDULE;
import org.alfresco.utility.report.Bug;
+import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@@ -83,6 +87,9 @@ public class RecordCategoryTests extends BaseRMRestTest
private static final int NUMBER_OF_CHILDREN = 10;
private static final int NUMBER_OF_FOLDERS = 5;
+ @Autowired
+ private RecordCategoriesAPI recordCategoriesAPI;
+
/**
* Invalid containers that cannot be deleted with record category end-point
*/
@@ -287,6 +294,7 @@ public class RecordCategoryTests extends BaseRMRestTest
assertEquals(folderProperties.getTitle(), TITLE_PREFIX + RECORD_FOLDER_NAME);
assertNotNull(folderProperties.getIdentifier());
}
+
/**
*
* Given that a record category exists
@@ -294,17 +302,37 @@ public class RecordCategoryTests extends BaseRMRestTest
* When I ask the API to get me the children of the record category
* Then I am returned the contained record categories and record folders and their details
*
+ *
+ * Given that a record category with a disposition schedule exists
+ * And contains a number of record categories and record folders
+ * When I ask the API to get me the children of the record category
+ * Then I am returned the contained record categories and record folders but not the disposition schedule
+ *
*/
@Test
- (
- description = "Get children of a record category"
- )
+ (
+ description = "Get children of a record category excluding the disposition schedule"
+ )
+ @Bug (id="RM-5115")
public void getRecordCategoryChildren() throws Exception
{
// Create root level category
RecordCategory rootRecordCategory = createRootCategory(getRandomAlphanumeric());
assertNotNull(rootRecordCategory.getId());
+ // Create disposition schedule
+ String userName = getAdminUser().getUsername();
+ String userPassword = getAdminUser().getPassword();
+ String categoryName = rootRecordCategory.getName();
+ recordCategoriesAPI.createRetentionSchedule(userName, userPassword, categoryName);
+
+ // Add disposition schedule cut off step
+ HashMap cutOffStep = new HashMap<>();
+ cutOffStep.put(RETENTION_SCHEDULE.NAME, "cutoff");
+ cutOffStep.put(RETENTION_SCHEDULE.RETENTION_PERIOD, "day|2");
+ cutOffStep.put(RETENTION_SCHEDULE.DESCRIPTION, "Cut off after 2 days");
+ recordCategoriesAPI.addDispositionScheduleSteps(userName, userPassword, categoryName, cutOffStep);
+
// Add record category children
List children = new ArrayList();
for (int i=0; i < NUMBER_OF_CHILDREN; i++)
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/fileplans/FilePlanChildrenRelation.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/fileplans/FilePlanChildrenRelation.java
index fce0877b72..923b70c636 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/fileplans/FilePlanChildrenRelation.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/fileplans/FilePlanChildrenRelation.java
@@ -198,8 +198,8 @@ public class FilePlanChildrenRelation implements RelationshipResourceAction.Read
for (RecordCategory nodeInfo : nodeInfos)
{
// Create the node
- NodeRef newNodeRef = apiUtils.createRMNode(parentNodeRef, nodeInfo.getName(), RECORD_CATEGORY_TYPE,
- nodeInfo.getProperties(), nodeInfo.getAspectNames());
+ nodeInfo.setNodeType(RECORD_CATEGORY_TYPE);
+ NodeRef newNodeRef = apiUtils.createRMNode(parentNodeRef, nodeInfo, parameters);
createdNodes.add(newNodeRef);
}
return createdNodes;
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/FilePlanComponentsApiUtils.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/FilePlanComponentsApiUtils.java
index 7ba7add131..8efd431607 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/FilePlanComponentsApiUtils.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/FilePlanComponentsApiUtils.java
@@ -134,6 +134,12 @@ public class FilePlanComponentsApiUtils
RecordsManagementModel.TYPE_UNFILED_RECORD_FOLDER,
RecordsManagementModel.TYPE_HOLD_CONTAINER);
+ public static final List TYPES_CAN_USE_AUTORENAME = Arrays.asList(
+ RecordsManagementModel.TYPE_RECORD_CATEGORY,
+ RecordsManagementModel.TYPE_RECORD_FOLDER,
+ RecordsManagementModel.TYPE_UNFILED_RECORD_CONTAINER,
+ RecordsManagementModel.TYPE_UNFILED_RECORD_FOLDER);
+
/** RM Nodes API */
private Nodes nodes;
private FileFolderService fileFolderService;
@@ -598,27 +604,43 @@ public class FilePlanComponentsApiUtils
* Create an RM node
*
* @param parentNodeRef the parent of the node
- * @param name the name of the new node
- * @param type the type of the node
- * @param properties properties to set on the new node
- * @param aspects aspects to set on the new node
+ * @param nodeInfo the node infos to create
+ * @param parameters the object to get the parameters passed into the request
* @return the new node
*/
- public NodeRef createRMNode(NodeRef parentNodeRef, String name, String type, Map properties, List aspects)
+ public NodeRef createRMNode(NodeRef parentNodeRef, RMNode nodeInfo, Parameters parameters)
{
mandatory("parentNodeRef", parentNodeRef);
- checkNotBlank(RMNode.PARAM_NAME, name);
- checkNotBlank(RMNode.PARAM_NODE_TYPE, type);
+ mandatory("nodeInfo", nodeInfo);
+ mandatory("parameters", parameters);
+
+ String nodeName = nodeInfo.getName();
+ String nodeType = nodeInfo.getNodeType();
+ checkNotBlank(RMNode.PARAM_NAME, nodeName);
+ checkNotBlank(RMNode.PARAM_NODE_TYPE, nodeType);
// Create the node
NodeRef newNodeRef = null;
+ boolean autoRename = Boolean.valueOf(parameters.getParameter(RMNode.PARAM_AUTO_RENAME));
+
try
{
- QName typeQName = nodes.createQName(type);
- newNodeRef = fileFolderService.create(parentNodeRef, name, typeQName).getNodeRef();
+ QName typeQName = nodes.createQName(nodeType);
+
+ // Existing file/folder name handling
+ if (TYPES_CAN_USE_AUTORENAME.contains(typeQName) && autoRename)
+ {
+ NodeRef existingNode = nodeService.getChildByName(parentNodeRef, ContentModel.ASSOC_CONTAINS, nodeName);
+ if (existingNode != null)
+ {
+ // File already exists, find a unique name
+ nodeName = findUniqueName(parentNodeRef, nodeName);
+ }
+ }
+ newNodeRef = fileFolderService.create(parentNodeRef, nodeName, typeQName).getNodeRef();
// Set the provided properties if any
- Map qnameProperties = mapToNodeProperties(properties);
+ Map qnameProperties = mapToNodeProperties(nodeInfo.getProperties());
if (qnameProperties != null)
{
nodeService.addProperties(newNodeRef, qnameProperties);
@@ -628,18 +650,19 @@ public class FilePlanComponentsApiUtils
if (!typeQName.equals(RecordsManagementModel.TYPE_NON_ELECTRONIC_DOCUMENT)
&& dictionaryService.isSubClass(typeQName, ContentModel.TYPE_CONTENT))
{
- writeContent(newNodeRef, name, new ByteArrayInputStream("".getBytes()), false);
+ writeContent(newNodeRef, nodeName, new ByteArrayInputStream("".getBytes()), false);
}
// Add the provided aspects if any
- if (aspects != null)
+ List aspectNames = nodeInfo.getAspectNames();
+ if (aspectNames != null)
{
- nodes.addCustomAspects(newNodeRef, aspects, ApiNodesModelFactory.EXCLUDED_ASPECTS);
+ nodes.addCustomAspects(newNodeRef, aspectNames, ApiNodesModelFactory.EXCLUDED_ASPECTS);
}
}
catch (InvalidTypeException ex)
{
- throw new InvalidArgumentException("The given type:'" + type + "' is invalid '");
+ throw new InvalidArgumentException("The given type:'" + nodeType + "' is invalid '");
}
return newNodeRef;
@@ -955,7 +978,45 @@ public class FilePlanComponentsApiUtils
activityPoster.postFileFolderActivity(activityType, null, TenantUtil.getCurrentDomain(), activityInfo.getSiteId(),
activityInfo.getParentNodeRef(), activityInfo.getNodeRef(), activityInfo.getFileName(), Activities.APP_TOOL,
Activities.RESTAPI_CLIENT, activityInfo.getFileInfo());
-
}
}
+ /**
+ * Creates a unique file name, if the upload component was configured to
+ * find a new unique name for clashing filenames.
+ *
+ * @param parentNodeRef the parent node
+ * @param fileName the original fileName
+ * @return a new file name
+ */
+ private String findUniqueName(NodeRef parentNodeRef, String fileName)
+ {
+ int counter = 1;
+ String tmpFilename;
+ NodeRef existingFile;
+ do
+ {
+ int dotIndex = fileName.lastIndexOf('.');
+ if (dotIndex == 0)
+ {
+ // File didn't have a proper 'name' instead it
+ // had just a suffix and started with a ".", create "1.txt"
+ tmpFilename = counter + fileName;
+ }
+ else if (dotIndex > 0)
+ {
+ // Filename contained ".", create "fileName-1.txt"
+ tmpFilename = fileName.substring(0, dotIndex) + "-" + counter + fileName.substring(dotIndex);
+ }
+ else
+ {
+ // Filename didn't contain a dot at all, create "fileName-1"
+ tmpFilename = fileName + "-" + counter;
+ }
+ existingFile = nodeService.getChildByName(parentNodeRef, ContentModel.ASSOC_CONTAINS, tmpFilename);
+ counter++;
+
+ } while (existingFile != null);
+
+ return tmpFilename;
+ }
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/SearchTypesFactory.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/SearchTypesFactory.java
index 2e103a9874..cbaee33f3b 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/SearchTypesFactory.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/SearchTypesFactory.java
@@ -198,6 +198,7 @@ public class SearchTypesFactory
Boolean isRecordFolder = propertyWalker.getProperty(RecordCategoryChild.PARAM_IS_RECORD_FOLDER,
WhereClauseParser.EQUALS, Boolean.class);
Boolean isRecordCategory = propertyWalker.getProperty(RecordCategoryChild.PARAM_IS_RECORD_CATEGORY, WhereClauseParser.EQUALS, Boolean.class);
+
if ((isRecordFolder != null && isRecordFolder.booleanValue()) || (isRecordCategory != null && !isRecordCategory.booleanValue()))
{
includeRecordFolders = true;
@@ -221,6 +222,7 @@ public class SearchTypesFactory
if (nodeTypeQNameStr.equals(RecordsManagementModel.TYPE_RECORD_FOLDER))
{
includeRecordFolders = true;
+
}
else if (filterNodeTypeQName.equals(RecordsManagementModel.TYPE_RECORD_CATEGORY))
{
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/model/RMNode.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/model/RMNode.java
index d4d590e3e8..7ddc40ded9 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/model/RMNode.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/model/RMNode.java
@@ -57,6 +57,7 @@ public abstract class RMNode
public static final String PARAM_PROPERTIES = "properties";
public static final String PARAM_PATH = "path";
public static final String PARAM_ALLOWABLE_OPERATIONS = "allowableOperations";
+ public static final String PARAM_AUTO_RENAME = "autoRename";
public static final String PARAM_ISPRIMARY = "isPrimary";
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/recordcategories/RecordCategoryChildrenRelation.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/recordcategories/RecordCategoryChildrenRelation.java
index 8da2cbf427..e1bdb8a680 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/recordcategories/RecordCategoryChildrenRelation.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/recordcategories/RecordCategoryChildrenRelation.java
@@ -33,6 +33,7 @@ import static org.alfresco.util.ParameterCheck.mandatory;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
@@ -40,6 +41,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.query.PagingResults;
import org.alfresco.repo.node.getchildren.FilterProp;
@@ -123,10 +125,11 @@ public class RecordCategoryChildrenRelation implements RelationshipResourceActio
// list record categories and record folders
Set searchTypeQNames = searchTypesFactory.buildSearchTypesCategoriesEndpoint(parameters, LIST_RECORD_CATEGORY_CHILDREN_EQUALS_QUERY_PROPERTIES);
+ Set assocTypeQNames = Collections.singleton(ContentModel.ASSOC_CONTAINS);
List filterProps = apiUtils.getListChildrenFilterProps(parameters, LIST_RECORD_CATEGORY_CHILDREN_EQUALS_QUERY_PROPERTIES);
final PagingResults pagingResults = fileFolderService.list(parentNodeRef,
- null,
+ assocTypeQNames,
searchTypeQNames,
null,
apiUtils.getSortProperties(parameters),
@@ -189,8 +192,7 @@ public class RecordCategoryChildrenRelation implements RelationshipResourceActio
RecordsManagementModel.TYPE_RECORD_CATEGORY);
}
// Create the node
- NodeRef newNode = apiUtils.createRMNode(nodeParent, nodeInfo.getName(), nodeInfo.getNodeType(),
- nodeInfo.getProperties(), nodeInfo.getAspectNames());
+ NodeRef newNode = apiUtils.createRMNode(nodeParent, nodeInfo, parameters);
createdNodes.add(newNode);
}
return createdNodes;
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/recordfolders/RecordFolderChildrenRelation.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/recordfolders/RecordFolderChildrenRelation.java
index 84a6b1f84a..1b4fd75877 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/recordfolders/RecordFolderChildrenRelation.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/recordfolders/RecordFolderChildrenRelation.java
@@ -167,7 +167,7 @@ public class RecordFolderChildrenRelation implements RelationshipResourceAction.
List createdNodes = new LinkedList<>();
for (Record nodeInfo : nodeInfos)
{
- NodeRef newNodeRef = apiUtils.createRMNode(parentNodeRef, nodeInfo.getName(), nodeInfo.getNodeType(), nodeInfo.getProperties(), nodeInfo.getAspectNames());
+ NodeRef newNodeRef = apiUtils.createRMNode(parentNodeRef, nodeInfo, parameters);
createdNodes.add(newNodeRef);
}
return createdNodes;
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/unfiledcontainers/UnfiledContainerChildrenRelation.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/unfiledcontainers/UnfiledContainerChildrenRelation.java
index f163b7a796..34107358ff 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/unfiledcontainers/UnfiledContainerChildrenRelation.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/unfiledcontainers/UnfiledContainerChildrenRelation.java
@@ -186,7 +186,7 @@ public class UnfiledContainerChildrenRelation implements RelationshipResourceAct
List createdNodes = new LinkedList<>();
for (UnfiledContainerChild nodeInfo : nodeInfos)
{
- NodeRef newNodeRef = apiUtils.createRMNode(parentNodeRef, nodeInfo.getName(), nodeInfo.getNodeType(), nodeInfo.getProperties(), nodeInfo.getAspectNames());
+ NodeRef newNodeRef = apiUtils.createRMNode(parentNodeRef, nodeInfo, parameters);
createdNodes.add(newNodeRef);
}
return createdNodes;
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/unfiledrecordfolders/UnfiledRecordFolderChildrenRelation.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/unfiledrecordfolders/UnfiledRecordFolderChildrenRelation.java
index ec18fc0e25..9fff8274af 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/unfiledrecordfolders/UnfiledRecordFolderChildrenRelation.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/unfiledrecordfolders/UnfiledRecordFolderChildrenRelation.java
@@ -174,7 +174,7 @@ public class UnfiledRecordFolderChildrenRelation implements RelationshipResource
mandatory("parameters", parameters);
NodeRef parentNodeRef = apiUtils.lookupAndValidateNodeType(unfiledRecordFolderId, RecordsManagementModel.TYPE_UNFILED_RECORD_FOLDER);
-
+
// Create the children
RetryingTransactionCallback> callback = new RetryingTransactionCallback>()
{
@@ -193,7 +193,7 @@ public class UnfiledRecordFolderChildrenRelation implements RelationshipResource
nodeParent = parentNodeRef;
}
- NodeRef newNodeRef = apiUtils.createRMNode(nodeParent, nodeInfo.getName(), nodeInfo.getNodeType(), nodeInfo.getProperties(), nodeInfo.getAspectNames());
+ NodeRef newNodeRef = apiUtils.createRMNode(nodeParent, nodeInfo, parameters);
createdNodes.add(newNodeRef);
}
return createdNodes;