From cc4e58a96717ffb18605e6827d7acd51895f9dc6 Mon Sep 17 00:00:00 2001 From: gfertuso <44156864+Giovanni007@users.noreply.github.com> Date: Tue, 23 Jun 2020 11:49:49 +0100 Subject: [PATCH] Feature/repo 5172 node definition (#672) * [REPO-5172] Added Definition to Node API * [REPO-5172] fix braces style * [REPO-5172] Code review * [REPO-5172] Type information deleted from Definition * [REPO-5172] Added excluded properties * [REPO-5172] Deleted attribute isOverride from NodeDefinitionProperty * [REPO-5172] Added test * [REPO-5172] temporary change to traviso conf file for test purpose * [maven-release-plugin][skip ci] prepare release alfresco-remote-api-repo-5172-8.190-1 * [maven-release-plugin][skip ci] prepare for next development iteration * Revert "[REPO-5172] temporary change to travis conf file for test purpose" * [REPO-5172] fix import in NodeApiTest --- .../rest/api/NodeDefinitionMapper.java | 39 +++++ .../java/org/alfresco/rest/api/Nodes.java | 1 + .../api/impl/NodeDefinitionMapperImpl.java | 124 +++++++++++++++ .../org/alfresco/rest/api/impl/NodesImpl.java | 24 ++- .../org/alfresco/rest/api/model/Node.java | 11 ++ .../rest/api/model/NodeDefinition.java | 49 ++++++ .../api/model/NodeDefinitionConstraint.java | 92 +++++++++++ .../api/model/NodeDefinitionProperty.java | 147 ++++++++++++++++++ .../alfresco/public-rest-context.xml | 3 + .../alfresco/rest/api/tests/NodeApiTest.java | 105 +++++++++++++ .../rest/api/tests/client/data/Node.java | 11 ++ 11 files changed, 605 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/alfresco/rest/api/NodeDefinitionMapper.java create mode 100644 src/main/java/org/alfresco/rest/api/impl/NodeDefinitionMapperImpl.java create mode 100644 src/main/java/org/alfresco/rest/api/model/NodeDefinition.java create mode 100644 src/main/java/org/alfresco/rest/api/model/NodeDefinitionConstraint.java create mode 100644 src/main/java/org/alfresco/rest/api/model/NodeDefinitionProperty.java diff --git a/src/main/java/org/alfresco/rest/api/NodeDefinitionMapper.java b/src/main/java/org/alfresco/rest/api/NodeDefinitionMapper.java new file mode 100644 index 0000000000..918be2531d --- /dev/null +++ b/src/main/java/org/alfresco/rest/api/NodeDefinitionMapper.java @@ -0,0 +1,39 @@ +/* + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2020 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.rest.api; + +import org.alfresco.rest.api.model.NodeDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.cmr.i18n.MessageLookup; +/** + * Maps representations from TypeDefinition to NodeDefinition + * + * @author gfertuso + */ +public interface NodeDefinitionMapper +{ + NodeDefinition fromTypeDefinition(TypeDefinition typeDefinition, MessageLookup messageLookup); +} diff --git a/src/main/java/org/alfresco/rest/api/Nodes.java b/src/main/java/org/alfresco/rest/api/Nodes.java index 308e53b38e..5ea2836315 100644 --- a/src/main/java/org/alfresco/rest/api/Nodes.java +++ b/src/main/java/org/alfresco/rest/api/Nodes.java @@ -380,6 +380,7 @@ public interface Nodes String PARAM_INCLUDE_ISFAVORITE = "isFavorite"; String PARAM_INCLUDE_ASSOCIATION = "association"; + String PARAM_INCLUDE_DEFINITION = "definition"; String PARAM_ISFOLDER = "isFolder"; String PARAM_ISFILE = "isFile"; diff --git a/src/main/java/org/alfresco/rest/api/impl/NodeDefinitionMapperImpl.java b/src/main/java/org/alfresco/rest/api/impl/NodeDefinitionMapperImpl.java new file mode 100644 index 0000000000..edc477e126 --- /dev/null +++ b/src/main/java/org/alfresco/rest/api/impl/NodeDefinitionMapperImpl.java @@ -0,0 +1,124 @@ +/* + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2020 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.rest.api.impl; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.rest.api.NodeDefinitionMapper; +import org.alfresco.rest.api.model.NodeDefinitionConstraint; +import org.alfresco.rest.api.model.NodeDefinition; +import org.alfresco.rest.api.model.NodeDefinitionProperty; +import org.alfresco.service.cmr.dictionary.ConstraintDefinition; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +/** + * Maps representations from TypeDefinition to NodeDefinition + * + * @author gfertuso + */ +public class NodeDefinitionMapperImpl implements NodeDefinitionMapper +{ + + private final List EXCLUDED_NS = Arrays.asList(NamespaceService.SYSTEM_MODEL_1_0_URI); + private static final List EXCLUDED_PROPS = Arrays.asList(ContentModel.PROP_CONTENT); + + @Override + public NodeDefinition fromTypeDefinition(TypeDefinition typeDefinition, + MessageLookup messageLookup) + { + + if (typeDefinition == null) + { + throw new AlfrescoRuntimeException("Undefined definition for the node"); + } + NodeDefinition nodeDefinition = new NodeDefinition(); + nodeDefinition.setProperties(getProperties(typeDefinition.getProperties(), messageLookup)); + + return nodeDefinition; + } + + private boolean isPropertyExcluded(QName propertyName) + { + return EXCLUDED_NS.contains(propertyName.getNamespaceURI()) || EXCLUDED_PROPS.contains(propertyName); + } + + private List getProperties(Map propertiesMap, MessageLookup messageLookup) + { + return propertiesMap.values().stream() + .filter(p -> !isPropertyExcluded(p.getName())) + .map(p -> fromPropertyDefinitionToProperty(p , messageLookup)) + .collect(Collectors.toList()); + } + + private NodeDefinitionProperty fromPropertyDefinitionToProperty(PropertyDefinition propertyDefinition, + MessageLookup messageLookup) + { + NodeDefinitionProperty property = new NodeDefinitionProperty(); + property.setId(propertyDefinition.getName().toPrefixString()); + property.setTitle(propertyDefinition.getTitle(messageLookup)); + property.setDescription(propertyDefinition.getDescription(messageLookup)); + property.setDefaultValue(propertyDefinition.getDefaultValue()); + property.setDataType(propertyDefinition.getDataType().getName().toPrefixString()); + property.setIsMultiValued(propertyDefinition.isMultiValued()); + property.setIsMandatory(propertyDefinition.isMandatory()); + property.setIsMandatoryEnforced(propertyDefinition.isMandatoryEnforced()); + property.setIsProtected(propertyDefinition.isProtected()); + property.setConstraints(getConstraints(propertyDefinition.getConstraints(), messageLookup)); + + return property; + } + + private List getConstraints( Collection constraintDefinitions, + MessageLookup messageLookup) + { + + return constraintDefinitions.stream() + .filter(constraint -> constraint.getConstraint() != null) + .map(constraint -> fromConstraintDefinitionToConstraint(constraint, messageLookup)) + .collect(Collectors.toList()); + } + + private NodeDefinitionConstraint fromConstraintDefinitionToConstraint(ConstraintDefinition constraintDefinition, + MessageLookup messageLookup) + { + NodeDefinitionConstraint constraint = new NodeDefinitionConstraint(); + constraint.setId(constraintDefinition.getConstraint().getShortName()); + constraint.setType(constraintDefinition.getConstraint().getType()); + constraint.setTitle(constraintDefinition.getTitle(messageLookup)); + constraint.setDescription(constraintDefinition.getDescription(messageLookup)); + constraint.setParameters(constraintDefinition.getConstraint().getParameters()); + return constraint; + } + +} diff --git a/src/main/java/org/alfresco/rest/api/impl/NodesImpl.java b/src/main/java/org/alfresco/rest/api/impl/NodesImpl.java index 4dbceab44e..600c276337 100644 --- a/src/main/java/org/alfresco/rest/api/impl/NodesImpl.java +++ b/src/main/java/org/alfresco/rest/api/impl/NodesImpl.java @@ -80,10 +80,12 @@ import org.alfresco.repo.version.VersionModel; import org.alfresco.repo.virtual.store.VirtualStore; import org.alfresco.rest.antlr.WhereClauseParser; import org.alfresco.rest.api.Activities; +import org.alfresco.rest.api.NodeDefinitionMapper; import org.alfresco.rest.api.Nodes; import org.alfresco.rest.api.QuickShareLinks; import org.alfresco.rest.api.model.AssocChild; import org.alfresco.rest.api.model.AssocTarget; +import org.alfresco.rest.api.model.NodeDefinition; import org.alfresco.rest.api.model.Document; import org.alfresco.rest.api.model.Folder; import org.alfresco.rest.api.model.LockInfo; @@ -125,6 +127,7 @@ import org.alfresco.service.cmr.dictionary.AspectDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.lock.LockService; import org.alfresco.service.cmr.lock.NodeLockedException; import org.alfresco.service.cmr.model.FileExistsException; @@ -215,6 +218,7 @@ public class NodesImpl implements Nodes private RetryingTransactionHelper retryingTransactionHelper; private LockService lockService; private VirtualStore smartStore; // note: remove as part of REPO-1173 + private NodeDefinitionMapper nodeDefinitionMapper; private enum Activity_Type { @@ -312,6 +316,11 @@ public class NodesImpl implements Nodes { this.smartStore = smartStore; } + + public void setNodeDefinitionMapper(NodeDefinitionMapper nodeDefinitionMapper) + { + this.nodeDefinitionMapper = nodeDefinitionMapper; + } // excluded namespaces (aspects, properties, assoc types) private static final List EXCLUDED_NS = Arrays.asList(NamespaceService.SYSTEM_MODEL_1_0_URI); @@ -1026,12 +1035,26 @@ public class NodesImpl implements Nodes } } + if (includeParam.contains(PARAM_INCLUDE_DEFINITION)) + { + NodeDefinition nodeDefinition = nodeDefinitionMapper.fromTypeDefinition(getTypeDefinition(nodeRef), dictionaryService); + node.setDefinition(nodeDefinition); + } + node.setNodeType(nodeTypeQName.toPrefixString(namespaceService)); node.setPath(pathInfo); return node; } + private TypeDefinition getTypeDefinition(NodeRef nodeRef) + { + QName type = nodeService.getType(nodeRef); + Set aspectNames = nodeService.getAspects(nodeRef); + TypeDefinition typeDefinition = dictionaryService.getAnonymousType(type, aspectNames); + return typeDefinition; + } + @Override public PathInfo lookupPathInfo(NodeRef nodeRefIn, ChildAssociationRef archivedParentAssoc) { @@ -3668,4 +3691,3 @@ public class NodesImpl implements Nodes return repositoryHelper; } } - diff --git a/src/main/java/org/alfresco/rest/api/model/Node.java b/src/main/java/org/alfresco/rest/api/model/Node.java index 055d70c951..9f3827d8f4 100644 --- a/src/main/java/org/alfresco/rest/api/model/Node.java +++ b/src/main/java/org/alfresco/rest/api/model/Node.java @@ -95,6 +95,7 @@ public class Node implements Comparable protected List allowableOperations; protected NodePermissions nodePermissions; + protected NodeDefinition definition; //optional SearchEntry (only ever returned from a search) protected SearchEntry search = null; @@ -469,6 +470,16 @@ public class Node implements Comparable this.secondaryChildren = secondaryChildren; } + public NodeDefinition getDefinition() + { + return definition; + } + + public void setDefinition(NodeDefinition definition) + { + this.definition = definition; + } + @Override public int compareTo(Node node) { diff --git a/src/main/java/org/alfresco/rest/api/model/NodeDefinition.java b/src/main/java/org/alfresco/rest/api/model/NodeDefinition.java new file mode 100644 index 0000000000..227a150623 --- /dev/null +++ b/src/main/java/org/alfresco/rest/api/model/NodeDefinition.java @@ -0,0 +1,49 @@ +/* + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2020 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.rest.api.model; + +import java.util.List; +/** + * Represents the node definition. + * + * @author gfertuso + */ +public class NodeDefinition +{ + + List properties; + + public List getProperties() + { + return properties; + } + + public void setProperties(List properties) + { + this.properties = properties; + } + +} diff --git a/src/main/java/org/alfresco/rest/api/model/NodeDefinitionConstraint.java b/src/main/java/org/alfresco/rest/api/model/NodeDefinitionConstraint.java new file mode 100644 index 0000000000..8a7cbcb6fc --- /dev/null +++ b/src/main/java/org/alfresco/rest/api/model/NodeDefinitionConstraint.java @@ -0,0 +1,92 @@ +/* + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2020 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.rest.api.model; + +import java.util.Map; +/** + * Represents a constraint of a node definition property. + * + * @author gfertuso + */ +public class NodeDefinitionConstraint +{ + private String id; + private String type; + private String title; + private String description; + private Map parameters; + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public String getType() + { + return type; + } + + public void setType(String type) + { + this.type = type; + } + + public String getTitle() + { + return title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public String getDescription() + { + return description; + } + + public void setDescription(String description) + { + this.description = description; + } + + public Map getParameters() + { + return parameters; + } + + public void setParameters(Map parameters) + { + this.parameters = parameters; + } + +} \ No newline at end of file diff --git a/src/main/java/org/alfresco/rest/api/model/NodeDefinitionProperty.java b/src/main/java/org/alfresco/rest/api/model/NodeDefinitionProperty.java new file mode 100644 index 0000000000..c07d02c066 --- /dev/null +++ b/src/main/java/org/alfresco/rest/api/model/NodeDefinitionProperty.java @@ -0,0 +1,147 @@ +/* + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2020 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.rest.api.model; + +import java.util.List; +/** + * Represents a property of the node definition. + * + * @author gfertuso + */ +public class NodeDefinitionProperty +{ + private String id; + private String title; + private String description; + private String defaultValue; + private String dataType; + private Boolean isMultiValued; + private Boolean isMandatory; + private Boolean isMandatoryEnforced; + private Boolean isProtected; + private List constraints; + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public String getTitle() + { + return title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public String getDescription() + { + return description; + } + + public void setDescription(String description) + { + this.description = description; + } + + public String getDefaultValue() + { + return defaultValue; + } + + public void setDefaultValue(String defaultValue) + { + this.defaultValue = defaultValue; + } + + public String getDataType() + { + return dataType; + } + + public void setDataType(String dataType) + { + this.dataType = dataType; + } + + public boolean getIsProtected() + { + return isProtected; + } + + public void setIsProtected(boolean isProtected) + { + this.isProtected = isProtected; + } + + public List getConstraints() + { + return constraints; + } + + public void setConstraints(List constraints) + { + this.constraints = constraints; + } + + public boolean getIsMultiValued() + { + return isMultiValued; + } + + public void setIsMultiValued(boolean isMultiValued) + { + this.isMultiValued = isMultiValued; + } + + public boolean getIsMandatory() + { + return isMandatory; + } + + public void setIsMandatory(boolean isMandatory) + { + this.isMandatory = isMandatory; + } + + public boolean getIsMandatoryEnforced() + { + return isMandatoryEnforced; + } + + public void setIsMandatoryEnforced(boolean isMandatoryEnforced) + { + this.isMandatoryEnforced = isMandatoryEnforced; + } + +} \ No newline at end of file diff --git a/src/main/resources/alfresco/public-rest-context.xml b/src/main/resources/alfresco/public-rest-context.xml index 2e22ddb029..52542c8e1b 100644 --- a/src/main/resources/alfresco/public-rest-context.xml +++ b/src/main/resources/alfresco/public-rest-context.xml @@ -518,6 +518,8 @@ + + @@ -527,6 +529,7 @@ + diff --git a/src/test/java/org/alfresco/rest/api/tests/NodeApiTest.java b/src/test/java/org/alfresco/rest/api/tests/NodeApiTest.java index f76a0c88be..45ca3ba657 100644 --- a/src/test/java/org/alfresco/rest/api/tests/NodeApiTest.java +++ b/src/test/java/org/alfresco/rest/api/tests/NodeApiTest.java @@ -53,6 +53,7 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.TimeUnit; +import org.alfresco.model.ContentModel; import org.alfresco.repo.content.ContentLimitProvider.SimpleFixedLimitProvider; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.security.authentication.AuthenticationUtil; @@ -61,8 +62,11 @@ import org.alfresco.repo.tenant.TenantUtil; import org.alfresco.rest.AbstractSingleNetworkSiteTest; import org.alfresco.rest.api.Nodes; import org.alfresco.rest.api.model.LockInfo; +import org.alfresco.rest.api.model.NodeDefinition; +import org.alfresco.rest.api.model.NodeDefinitionConstraint; import org.alfresco.rest.api.model.NodePermissions; import org.alfresco.rest.api.model.NodeTarget; +import org.alfresco.rest.api.model.NodeDefinitionProperty; import org.alfresco.rest.api.model.Site; import org.alfresco.rest.api.nodes.NodesEntityResource; import org.alfresco.rest.api.tests.client.HttpResponse; @@ -95,6 +99,7 @@ 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.cmr.site.SiteVisibility; +import org.alfresco.service.namespace.NamespaceService; import org.alfresco.util.GUID; import org.alfresco.util.TempFileProvider; import org.apache.commons.collections.map.MultiValueMap; @@ -130,6 +135,8 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest protected PermissionService permissionService; protected AuthorityService authorityService; private NodeService nodeService; + private NamespaceService namespaceService; + private String rootGroupName = null; private String groupA = null; @@ -143,6 +150,7 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest permissionService = applicationContext.getBean("permissionService", PermissionService.class); authorityService = (AuthorityService) applicationContext.getBean("AuthorityService"); nodeService = applicationContext.getBean("NodeService", NodeService.class); + namespaceService= (NamespaceService) applicationContext.getBean("NamespaceService"); } @After @@ -5885,5 +5893,102 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest return "public"; } + @Test + public void testRetrieveNodeDefinition() throws Exception + { + setRequestContext(networkOne.getId(), user1, null); + + String node1 = "nodeSample" + RUNID + "_1"; + String node1Type = TYPE_CM_CONTENT; + Map props = new HashMap<>(); + props.put("cm:title", "add aspect property"); + Node node = createNode(Nodes.PATH_MY, node1, node1Type, props); + String nodeId = node.getId(); + + HttpResponse response = getSingle(NodesEntityResource.class, nodeId, null, 200); + Node nodeResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Node.class); + assertNull("Definition should not be retrieved unless included!", nodeResp.getDefinition()); + + Map params = new HashMap<>(); + params.put("include", "definition"); + response = getSingle(NodesEntityResource.class, nodeId, params, 200); + nodeResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Node.class); + NodeDefinition nodeDefinition = nodeResp.getDefinition(); + assertNotNull(nodeDefinition); + checkDefinitionProperties(nodeDefinition.getProperties()); + } + + private void checkDefinitionProperties(List properties) + { + assertNotNull(properties); + shouldNotContainSystemProperties(properties); + shouldContainParentProperties(properties); + shouldContainAspectProperties(properties); + + NodeDefinitionProperty testProperty = properties.stream(). + filter(property -> + property.getId().equals("cm:name")) + .findFirst() + .get(); + assertNotNull(testProperty); + assertEquals("Name", testProperty.getTitle()); + assertEquals("d:text", testProperty.getDataType()); + assertEquals("Name", testProperty.getDescription()); + assertTrue(testProperty.getIsMandatory()); + assertTrue(testProperty.getIsMandatoryEnforced()); + assertFalse(testProperty.getIsMultiValued()); + assertNull(testProperty.getDefaultValue()); + checkPropertyConstraints(testProperty.getConstraints()); + + } + + private void shouldNotContainSystemProperties(List properties) + { + assertTrue(properties.stream() + .noneMatch(property -> + property.getId().startsWith(NamespaceService.SYSTEM_MODEL_PREFIX) || + property.getId().equals(ContentModel.PROP_CONTENT.toPrefixString(namespaceService)))); + } + + private void shouldContainParentProperties(List properties) + { + assertTrue(properties.stream() + .anyMatch(property -> + property.getId().equals("cm:name"))); + } + + private void shouldContainAspectProperties(List properties) + { + NodeDefinitionProperty mandatoryAspectProperty = properties.stream() + .filter(property -> property.getId().equals("cm:created")) + .findFirst() + .get(); + assertNotNull(mandatoryAspectProperty); + + NodeDefinitionProperty nodeAspectProperty = properties.stream() + .filter(property -> property.getId().equals("cm:title")) + .findFirst() + .get(); + assertNotNull(nodeAspectProperty); + } + + private void checkPropertyConstraints(List constraints) + { + assertNotNull(constraints); + NodeDefinitionConstraint nodeDefinitionConstraint = constraints.stream() + .filter(constraint -> constraint.getId().equals("cm:filename")) + .findFirst() + .get(); + assertNotNull(nodeDefinitionConstraint); + assertEquals("REGEX", nodeDefinitionConstraint.getType()); + Map constraintParameters = nodeDefinitionConstraint.getParameters(); + assertNotNull(constraintParameters); + assertNull(nodeDefinitionConstraint.getDescription()); + assertNull(nodeDefinitionConstraint.getTitle()); + assertEquals(2, constraintParameters.size()); + assertEquals("(.*[\\\"\\*\\\\\\>\\<\\?\\/\\:\\|]+.*)|(.*[\\.]?.*[\\.]+$)|(.*[ ]+$)", constraintParameters.get("expression")); + assertFalse((Boolean) constraintParameters.get("requiresMatch")); + } + } diff --git a/src/test/java/org/alfresco/rest/api/tests/client/data/Node.java b/src/test/java/org/alfresco/rest/api/tests/client/data/Node.java index ff191acaed..91bd1cd73d 100644 --- a/src/test/java/org/alfresco/rest/api/tests/client/data/Node.java +++ b/src/test/java/org/alfresco/rest/api/tests/client/data/Node.java @@ -27,6 +27,7 @@ package org.alfresco.rest.api.tests.client.data; import org.alfresco.rest.api.model.AssocChild; import org.alfresco.rest.api.model.AssocTarget; +import org.alfresco.rest.api.model.NodeDefinition; import org.alfresco.rest.api.model.NodePermissions; import java.util.Date; @@ -79,6 +80,7 @@ public class Node protected List allowableOperations; protected NodePermissions nodePermissions; + protected NodeDefinition definition; // please note: these are currently only used (optionally) for node create request protected String relativePath; @@ -323,6 +325,15 @@ public class Node this.targets = targets; } + public NodeDefinition getDefinition() + { + return definition; + } + + public void setDefinition(NodeDefinition definition) + { + this.definition = definition; + } // note: can be child or peer (latter has assocType only) protected Association association;