diff --git a/source/java/org/alfresco/rest/api/impl/NodesImpl.java b/source/java/org/alfresco/rest/api/impl/NodesImpl.java
index 519ecf6a7c..ba8c941d15 100644
--- a/source/java/org/alfresco/rest/api/impl/NodesImpl.java
+++ b/source/java/org/alfresco/rest/api/impl/NodesImpl.java
@@ -1062,7 +1062,7 @@ public class NodesImpl implements Nodes
}
else
{
- throw new IllegalArgumentException("Failed to change (specialise) the node type - from "+nodeTypeQName+" to "+destNodeTypeQName);
+ throw new InvalidArgumentException("Failed to change (specialise) node type - from "+nodeTypeQName+" to "+destNodeTypeQName);
}
}
@@ -1123,8 +1123,15 @@ public class NodesImpl implements Nodes
if (props.size() > 0)
{
- // update node properties - note: null will unset the specified property
- nodeService.addProperties(nodeRef, props);
+ try
+ {
+ // update node properties - note: null will unset the specified property
+ nodeService.addProperties(nodeRef, props);
+ }
+ catch (DuplicateChildNodeNameException dcne)
+ {
+ throw new ConstraintViolatedException(dcne.getMessage());
+ }
}
return getFolderOrDocument(nodeRef.getId(), parameters);
diff --git a/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java b/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java
index 8efe0ee00a..06af6f4c8e 100644
--- a/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java
+++ b/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java
@@ -745,7 +745,7 @@ public class NodeApiTest extends AbstractBaseApiTest
}
/**
- * Tests delete (folder or file).
+ * Tests delete (file or folder)
*
DELETE:
* {@literal :/alfresco/api/-default-/public/alfresco/versions/1/nodes/}
*/
@@ -960,6 +960,199 @@ public class NodeApiTest extends AbstractBaseApiTest
post(postUrl, user1, toJsonAsStringNonNull(d1), 409);
}
+ /**
+ * Tests update node info (file or folder)
+ * PUT:
+ * {@literal :/alfresco/api/-default-/public/alfresco/versions/1/nodes/}
+ */
+ @Test
+ public void testUpdateNodeInfo() throws Exception
+ {
+ AuthenticationUtil.setFullyAuthenticatedUser(user1);
+
+ NodeRef personNodeRef = personService.getPerson(user1);
+ NodeRef myFilesNodeRef = repositoryHelper.getUserHome(personNodeRef);
+
+ UserInfo expectedUser = new UserInfo(user1, user1+" "+user1);
+
+ String postUrl = "nodes/"+myFilesNodeRef.getId()+"/children";
+
+ String folderName = "My Folder";
+
+ // create folder
+
+ Folder f1 = new Folder();
+ f1.setName(folderName);
+ f1.setNodeType("cm:folder");
+
+ HttpResponse response = post(postUrl, user1, toJsonAsStringNonNull(f1), 201);
+ Folder folderResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Folder.class);
+
+ String fId = folderResp.getId();
+
+ f1.setIsFolder(true);
+ f1.setParentId(myFilesNodeRef.getId());
+ f1.setAspectNames(Collections.singletonList("cm:auditable"));
+
+ f1.setCreatedByUser(expectedUser);
+ f1.setModifiedByUser(expectedUser);
+
+ f1.expected(folderResp);
+
+ // create empty file
+
+ Document d1 = new Document();
+ d1.setName("d1.txt");
+ d1.setNodeType("cm:content");
+ ContentInfo ci = new ContentInfo();
+ ci.setMimeType("text/plain");
+ d1.setContent(ci);
+
+ response = post(postUrl, user1, toJsonAsStringNonNull(d1), 201);
+ Document documentResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
+
+ String dId = documentResp.getId();
+
+ d1.setIsFolder(false);
+ d1.setParentId(myFilesNodeRef.getId());
+ d1.setAspectNames(Collections.singletonList("cm:auditable"));
+
+ d1.setCreatedByUser(expectedUser);
+ d1.setModifiedByUser(expectedUser);
+
+ d1.getContent().setMimeTypeName("Plain Text");
+ d1.getContent().setSizeInBytes(0L);
+ d1.getContent().setEncoding("UTF-8");
+
+ d1.expected(documentResp);
+
+ // update file - name (=> rename within current folder)
+
+ Document dUpdate = new Document();
+ dUpdate.setName("d1b.txt");
+
+ response = put("nodes", user1, dId, toJsonAsStringNonNull(dUpdate), null, 200);
+ documentResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
+
+ d1.setName("d1b.txt");
+ d1.expected(documentResp);
+
+ // update file - add some properties
+
+ Map props = new HashMap<>();
+ props.put("cm:title","my file title");
+ props.put("cm:description","my file description");
+
+ dUpdate = new Document();
+ dUpdate.setProperties(props);
+
+ response = put("nodes", user1, dId, toJsonAsStringNonNull(dUpdate), null, 200);
+ documentResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
+
+ d1.setProperties(props);
+ d1.setAspectNames(Arrays.asList("cm:auditable","cm:titled"));
+ d1.expected(documentResp);
+
+ // update file - add versionable aspect
+
+ dUpdate = new Document();
+ dUpdate.setAspectNames(Arrays.asList("cm:auditable","cm:titled","cm:versionable"));
+
+ response = put("nodes", user1, dId, toJsonAsStringNonNull(dUpdate), null, 200);
+ documentResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
+
+ //d1.getProperties().put("cm:versionLabel","1.0"); // TODO ... fix api ?!
+ d1.setAspectNames(Arrays.asList("cm:auditable","cm:titled","cm:versionable"));
+ d1.expected(documentResp);
+
+ response = getSingle("nodes", user1, dId, 200);
+ documentResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
+
+ d1.getProperties().put("cm:versionLabel","1.0");
+ d1.expected(documentResp);
+
+ // update file - remove titled aspect (and it's related aspect properties)
+
+ dUpdate = new Document();
+ dUpdate.setAspectNames(Arrays.asList("cm:auditable","cm:versionable"));
+
+ response = put("nodes", user1, dId, toJsonAsStringNonNull(dUpdate), null, 200);
+ documentResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
+
+ d1.getProperties().remove("cm:title");
+ d1.getProperties().remove("cm:description");
+ d1.setAspectNames(Arrays.asList("cm:auditable","cm:versionable"));
+ d1.expected(documentResp);
+
+ // update folder - rename and add some properties
+
+ props = new HashMap<>();
+ props.put("cm:title","my folder title");
+ props.put("cm:description","my folder description");
+
+ folderName = "My Updated Folder";
+ Folder fUpdate = new Folder();
+ fUpdate.setProperties(props);
+ fUpdate.setName(folderName);
+
+ response = put("nodes", user1, fId, toJsonAsStringNonNull(fUpdate), null, 200);
+ folderResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Folder.class);
+
+ f1.setName(folderName);
+ f1.setAspectNames(Arrays.asList("cm:auditable","cm:titled"));
+ f1.setProperties(props);
+ f1.expected(folderResp);
+
+ // update folder - unset a property
+
+ props = new HashMap<>();
+ props.put("cm:title",null);
+
+ fUpdate = new Folder();
+ fUpdate.setProperties(props);
+
+ response = put("nodes", user1, fId, toJsonAsStringNonNull(fUpdate), null, 200);
+ folderResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Folder.class);
+
+ f1.getProperties().remove("cm:title");
+ f1.expected(folderResp);
+
+ // update folder - specialise node type
+
+ fUpdate = new Folder();
+ fUpdate.setNodeType("app:glossary");
+
+ response = put("nodes", user1, fId, toJsonAsStringNonNull(fUpdate), null, 200);
+ folderResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Folder.class);
+
+ f1.setNodeType("app:glossary");
+ f1.expected(folderResp);
+
+ // -ve test - ignore unknown property
+ props = new HashMap<>();
+ props.put("cm:xyz","my unknown property");
+ dUpdate = new Document();
+ dUpdate.setProperties(props);
+ response = put("nodes", user1, dId, toJsonAsStringNonNull(dUpdate), null, 200);
+ documentResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
+ d1.expected(documentResp);
+
+ // -ve test - duplicate name
+ dUpdate = new Document();
+ dUpdate.setName(folderName);
+ put("nodes", user1, dId, toJsonAsStringNonNull(dUpdate), null, 409);
+
+ // -ve test - unknown node id
+ dUpdate = new Document();
+ dUpdate.setName("some.txt");
+ put("nodes", user1, UUID.randomUUID().toString(), toJsonAsStringNonNull(dUpdate), null, 404);
+
+ // -ve test - generalise node type
+ fUpdate = new Folder();
+ fUpdate.setNodeType("cm:folder");
+ put("nodes", user1, fId, toJsonAsStringNonNull(fUpdate), null, 400);
+ }
+
// TODO add test to create multiple folders & empty files (within same parent folder)
// TODO add test for file/folder links - creating, getting, listing, deleting