diff --git a/source/java/org/alfresco/rest/api/impl/NodesImpl.java b/source/java/org/alfresco/rest/api/impl/NodesImpl.java index 734adc5247..c3f3cd3368 100644 --- a/source/java/org/alfresco/rest/api/impl/NodesImpl.java +++ b/source/java/org/alfresco/rest/api/impl/NodesImpl.java @@ -37,6 +37,7 @@ import org.alfresco.rest.api.model.Folder; import org.alfresco.rest.api.model.Node; import org.alfresco.rest.api.model.PathInfo; import org.alfresco.rest.api.model.PathInfo.ElementInfo; +import org.alfresco.rest.api.model.UserInfo; import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; import org.alfresco.rest.framework.resource.content.BasicContentInfo; @@ -151,7 +152,7 @@ public class NodesImpl implements Nodes ContentModel.ASPECT_LOCALIZED); private static final List EXCLUDED_PROPS = Arrays.asList( - // top-level basic info + // top-level minimal info ContentModel.PROP_NAME, ContentModel.PROP_MODIFIER, ContentModel.PROP_MODIFIED, @@ -170,6 +171,13 @@ public class NodesImpl implements Nodes ContentModel.PROP_AUTO_VERSION_PROPS, ContentModel.PROP_AUTO_VERSION); + private static final List PROPS_USERLOOKUP = Arrays.asList( + ContentModel.PROP_CREATOR, + ContentModel.PROP_MODIFIER, + ContentModel.PROP_OWNER, + ContentModel.PROP_LOCK_OWNER, + ContentModel.PROP_WORKING_COPY_OWNER); + private final static String PARAM_ISFOLDER = "isFolder"; private final static String PARAM_NAME = "name"; private final static String PARAM_CREATEDAT = "createdAt"; @@ -280,7 +288,7 @@ public class NodesImpl implements Nodes { NodeRef nodeRef = validateNode(nodeId); - return new Node(nodeRef, null, nodeService.getProperties(nodeRef), sr); + return new Node(nodeRef, null, nodeService.getProperties(nodeRef), null, sr); } /** @@ -288,7 +296,7 @@ public class NodesImpl implements Nodes */ public Node getNode(NodeRef nodeRef) { - return new Node(nodeRef, null, nodeService.getProperties(nodeRef), sr); + return new Node(nodeRef, null, nodeService.getProperties(nodeRef), null, sr); } private Type getType(NodeRef nodeRef) @@ -313,7 +321,7 @@ public class NodesImpl implements Nodes { Map properties = nodeService.getProperties(nodeRef); - Document doc = new Document(nodeRef, getParentNodeRef(nodeRef), properties, sr); + Document doc = new Document(nodeRef, getParentNodeRef(nodeRef), properties, null, sr); doc.setVersionLabel((String) properties.get(ContentModel.PROP_VERSION_LABEL)); ContentData cd = (ContentData) properties.get(ContentModel.PROP_CONTENT); @@ -351,7 +359,7 @@ public class NodesImpl implements Nodes { Map properties = nodeService.getProperties(nodeRef); - Folder folder = new Folder(nodeRef, getParentNodeRef(nodeRef), properties, sr); + Folder folder = new Folder(nodeRef, getParentNodeRef(nodeRef), properties, null, sr); setCommonProps(folder, nodeRef, properties); return folder; } @@ -468,14 +476,18 @@ public class NodesImpl implements Nodes NodeRef nodeRef = validateOrLookupNode(nodeId, path); QName typeQName = nodeService.getType(nodeRef); - List requestedProperties = createQNames(parameters.getSelectedProperties()); - return getFolderOrDocument(nodeRef, getParentNodeRef(nodeRef), typeQName, requestedProperties, false); + List requestedProperties = createQNames(parameters.getSelectedProperties()); + return getFolderOrDocument(nodeRef, getParentNodeRef(nodeRef), typeQName, requestedProperties, false, null); } - private Node getFolderOrDocument(final NodeRef nodeRef, NodeRef parentNodeRef, QName typeQName, List selectedProperties, boolean minimalnfo) + private Node getFolderOrDocument(final NodeRef nodeRef, NodeRef parentNodeRef, QName typeQName, List selectedProperties, boolean minimalInfo, Map mapUserInfo) { + if (mapUserInfo == null) { + mapUserInfo = new HashMap<>(2); + } + PathInfo pathInfo = null; - if (!minimalnfo) + if (!minimalInfo) { pathInfo = lookupPathInfo(nodeRef); } @@ -487,21 +499,21 @@ public class NodesImpl implements Nodes if (type.equals(Type.DOCUMENT)) { - node = new Document(nodeRef, parentNodeRef, properties, sr); + node = new Document(nodeRef, parentNodeRef, properties, mapUserInfo, sr); } else if (type.equals(Type.FOLDER)) { // container/folder - node = new Folder(nodeRef, parentNodeRef, properties, sr); + node = new Folder(nodeRef, parentNodeRef, properties, mapUserInfo, sr); } else { throw new InvalidArgumentException("Node is not a folder or file"); } - if (!minimalnfo) + if (! minimalInfo) { - node.setProperties(mapProperties(properties, selectedProperties)); + node.setProperties(mapProperties(properties, selectedProperties, mapUserInfo)); node.setAspectNames(mapAspects(nodeService.getAspects(nodeRef))); } @@ -613,7 +625,7 @@ public class NodesImpl implements Nodes return new PathInfo(pathStr, isComplete, pathElements); } - protected Map mapProperties(Map nodeProps, List selectedProperties) + protected Map mapProperties(Map nodeProps, List selectedProperties, Map mapUserInfo) { Map props = null; if (!selectedProperties.isEmpty()) @@ -624,6 +636,9 @@ public class NodesImpl implements Nodes Serializable value = nodeProps.get(qName); if (value != null) { + if (PROPS_USERLOOKUP.contains(qName)) { + value = Node.lookupUserInfo((String)value, mapUserInfo, sr.getPersonService()); + } props.put(qName.toPrefixString(namespaceService), value); } } @@ -658,18 +673,9 @@ public class NodesImpl implements Nodes public CollectionWithPagingInfo getChildren(String parentFolderNodeId, Parameters parameters) { - // TODO do we want to support path with list folder children ? - String path = null; - // String path = parameters.getParameter("path"); + final NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, null); - final NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, path); - - // TODO - // map - where (filter) properties - including isFolder - // map - orderBy (sort) properties - including isFolder - - // TODO refactor & fix ! - final boolean minimalnfo = (parameters.getSelectedProperties().size() == 0); + final boolean minimalInfo = (parameters.getSelectedProperties().size() == 0); final List requestedProperties = createQNames(parameters.getSelectedProperties()); boolean includeFolders = true; @@ -729,6 +735,8 @@ public class NodesImpl implements Nodes final PagingResults pagingResults = fileFolderService.list(parentNodeRef, includeFiles, includeFolders, ignoreTypeQNames, sortProps, pagingRequest); + final Map mapUserInfo = new HashMap<>(10); + final List page = pagingResults.getPage(); List nodes = new AbstractList() { @@ -737,8 +745,8 @@ public class NodesImpl implements Nodes { FileInfo fInfo = page.get(index); - // basic info by default (unless "select"ed otherwise) - return getFolderOrDocument(fInfo.getNodeRef(), parentNodeRef, fInfo.getType(), requestedProperties, minimalnfo); + // minimal info by default (unless "select"ed otherwise) + return getFolderOrDocument(fInfo.getNodeRef(), parentNodeRef, fInfo.getType(), requestedProperties, minimalInfo, mapUserInfo); } @Override @@ -796,7 +804,7 @@ public class NodesImpl implements Nodes { for (Entry entry : nodeInfo.getProperties().entrySet()) { - QName propQName = QName.createQName((String)entry.getKey(), namespaceService); + QName propQName = QName.createQName(entry.getKey(), namespaceService); props.put(propQName, (Serializable)entry.getValue()); } } @@ -834,7 +842,7 @@ public class NodesImpl implements Nodes { for (Entry entry : nodeInfo.getProperties().entrySet()) { - QName propQName = QName.createQName((String)entry.getKey(), namespaceService); + QName propQName = QName.createQName(entry.getKey(), namespaceService); props.put(propQName, (Serializable)entry.getValue()); } } diff --git a/source/java/org/alfresco/rest/api/model/Document.java b/source/java/org/alfresco/rest/api/model/Document.java index 37bacccaaf..8ce426e6b9 100644 --- a/source/java/org/alfresco/rest/api/model/Document.java +++ b/source/java/org/alfresco/rest/api/model/Document.java @@ -55,9 +55,9 @@ public class Document extends Node super(); } - public Document(NodeRef nodeRef, NodeRef parentNodeRef, Map nodeProps, ServiceRegistry sr) + public Document(NodeRef nodeRef, NodeRef parentNodeRef, Map nodeProps, Map mapUserInfo, ServiceRegistry sr) { - super(nodeRef, parentNodeRef, nodeProps, sr); + super(nodeRef, parentNodeRef, nodeProps, mapUserInfo, sr); Serializable val = nodeProps.get(ContentModel.PROP_CONTENT); diff --git a/source/java/org/alfresco/rest/api/model/Folder.java b/source/java/org/alfresco/rest/api/model/Folder.java index f6cb3dfbde..fbb2fe8897 100644 --- a/source/java/org/alfresco/rest/api/model/Folder.java +++ b/source/java/org/alfresco/rest/api/model/Folder.java @@ -51,9 +51,9 @@ public class Folder extends Node super(); } - public Folder(NodeRef nodeRef, NodeRef parentNodeRef, Map nodeProps, ServiceRegistry sr) + public Folder(NodeRef nodeRef, NodeRef parentNodeRef, Map nodeProps, Map mapUserInfo, ServiceRegistry sr) { - super(nodeRef, parentNodeRef, nodeProps, sr); + super(nodeRef, parentNodeRef, nodeProps, mapUserInfo, sr); } @Override diff --git a/source/java/org/alfresco/rest/api/model/Node.java b/source/java/org/alfresco/rest/api/model/Node.java index a08decd3bd..bd3a74be81 100644 --- a/source/java/org/alfresco/rest/api/model/Node.java +++ b/source/java/org/alfresco/rest/api/model/Node.java @@ -27,6 +27,7 @@ package org.alfresco.rest.api.model; import java.io.Serializable; import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -35,6 +36,7 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.rest.framework.resource.UniqueId; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.security.NoSuchPersonException; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.namespace.QName; import org.alfresco.util.EqualsHelper; @@ -67,9 +69,7 @@ public class Node implements Comparable protected Map properties; - // TODO fixme ! - // also need to optionally pass in user map - eg. when listing children (to avoid multiple lookups for same user) - public Node(NodeRef nodeRef, NodeRef parentNodeRef, Map nodeProps, ServiceRegistry sr) + public Node(NodeRef nodeRef, NodeRef parentNodeRef, Map nodeProps, Map mapUserInfo, ServiceRegistry sr) { if(nodeRef == null) { @@ -79,7 +79,7 @@ public class Node implements Comparable this.nodeRef = nodeRef; this.parentNodeRef = parentNodeRef; - mapMinimalInfo(nodeProps, sr); + mapMinimalInfo(nodeProps, mapUserInfo, sr); } protected Object getValue(Map> props, String name) @@ -93,39 +93,52 @@ public class Node implements Comparable { } - protected void mapMinimalInfo(Map nodeProps, ServiceRegistry sr) + protected void mapMinimalInfo(Map nodeProps, Map mapUserInfo, ServiceRegistry sr) { PersonService personService = sr.getPersonService(); - // TODO review backwards compat' for favorites & others (eg. set guid explicitly where still needed) - //this.guid = nodeRef; - //this.title = (String)nodeProps.get(ContentModel.PROP_TITLE); - //this.description = (String)nodeProps.get(ContentModel.PROP_DESCRIPTION); - //this.createdBy = (String)nodeProps.get(ContentModel.PROP_CREATOR); - //this.modifiedBy = (String)nodeProps.get(ContentModel.PROP_MODIFIER); - this.name = (String)nodeProps.get(ContentModel.PROP_NAME); + if (mapUserInfo == null) { + // minor: save one lookup if creator & modifier are the same + mapUserInfo = new HashMap<>(2); + } + this.createdAt = (Date)nodeProps.get(ContentModel.PROP_CREATED); - this.createdByUser = lookupUserInfo((String)nodeProps.get(ContentModel.PROP_CREATOR), personService); + this.createdByUser = lookupUserInfo((String)nodeProps.get(ContentModel.PROP_CREATOR), mapUserInfo, personService); this.modifiedAt = (Date)nodeProps.get(ContentModel.PROP_MODIFIED); - this.modifiedByUser = lookupUserInfo((String)nodeProps.get(ContentModel.PROP_MODIFIER), personService); + this.modifiedByUser = lookupUserInfo((String)nodeProps.get(ContentModel.PROP_MODIFIER), mapUserInfo, personService); } - // TODO refactor & optimise to avoid multiple person lookups - private UserInfo lookupUserInfo(final String userName, final PersonService personService) { + public static UserInfo lookupUserInfo(String userName, Map mapUserInfo, PersonService personService) { - String sysUserName = AuthenticationUtil.getSystemUserName(); - if (userName.equals(sysUserName) || (AuthenticationUtil.isMtEnabled() && userName.startsWith(sysUserName+"@"))) + UserInfo userInfo = mapUserInfo.get(userName); + if (userInfo == null) { - return new UserInfo(userName, userName, ""); - } - else - { - PersonService.PersonInfo pInfo = personService.getPerson(personService.getPerson(userName)); - return new UserInfo(userName, pInfo.getFirstName(), pInfo.getLastName()); + String sysUserName = AuthenticationUtil.getSystemUserName(); + if (userName.equals(sysUserName) || (AuthenticationUtil.isMtEnabled() && userName.startsWith(sysUserName + "@"))) + { + userInfo = new UserInfo(userName, userName, ""); + } + else + { + try + { + PersonService.PersonInfo pInfo = personService.getPerson(personService.getPerson(userName)); + userInfo = new UserInfo(userName, pInfo.getFirstName(), pInfo.getLastName()); + } + catch (NoSuchPersonException nspe) + { + // belts-and-braces (seen in dev/test env, eg. userName = Bobd58ba329-b702-41ee-a9ae-2b3c7029b5bc + userInfo = new UserInfo(userName, userName, ""); + } + + } + + mapUserInfo.put(userName, userInfo); } + return userInfo; } @UniqueId diff --git a/source/java/org/alfresco/rest/api/model/UserInfo.java b/source/java/org/alfresco/rest/api/model/UserInfo.java index c8d4950927..371dc9fcf4 100644 --- a/source/java/org/alfresco/rest/api/model/UserInfo.java +++ b/source/java/org/alfresco/rest/api/model/UserInfo.java @@ -19,12 +19,14 @@ package org.alfresco.rest.api.model; +import java.io.Serializable; + /** * Representation of a user info * * @author janv */ -public class UserInfo +public class UserInfo implements Serializable { private String userName; private String displayName; diff --git a/source/java/org/alfresco/rest/api/nodes/NodesEntityResource.java b/source/java/org/alfresco/rest/api/nodes/NodesEntityResource.java index a229674f75..ce536767b0 100644 --- a/source/java/org/alfresco/rest/api/nodes/NodesEntityResource.java +++ b/source/java/org/alfresco/rest/api/nodes/NodesEntityResource.java @@ -70,7 +70,7 @@ public class NodesEntityResource implements /** * Returns information regarding the node 'nodeId' - folder or document * - * @param nodeId String id of node (folder or document) - will also accept well-known aliases, eg. "-root-" or "-my-" + * @param nodeId String id of node (folder or document) - will also accept well-known aliases, eg. "-root-", "-my-", "-shared-" * * Optional parameters: * - path