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;