mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
Merged HEAD (5.2) to 5.2.N (5.2.1)
126349 jkaabimofrad: Merged FILE-FOLDER-API (5.2.0) to HEAD (5.2) 118692 jvonka: Merge from DEV/SABRE_JANV1 (part 2) - RA-613 / RA-655 - File Folder API (PoC - experimental WIP) - TODO add tests +review backwards compat' (eg. favs) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@126694 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -430,13 +430,8 @@
|
|||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="nodes" class="org.alfresco.rest.api.impl.NodesImpl">
|
<bean id="nodes" class="org.alfresco.rest.api.impl.NodesImpl">
|
||||||
<property name="nodeService" ref="NodeService" />
|
<property name="serviceRegistry" ref="ServiceRegistry"/>
|
||||||
<property name="dictionaryService" ref="DictionaryService" />
|
|
||||||
<property name="cmisConnector" ref="CMISConnector" />
|
|
||||||
<property name="fileFolderService" ref="FileFolderService" />
|
|
||||||
<property name="repositoryHelper" ref="repositoryHelper"/>
|
<property name="repositoryHelper" ref="repositoryHelper"/>
|
||||||
<property name="namespaceService" ref="NamespaceService" />
|
|
||||||
<property name="permissionService" ref="PermissionService" />
|
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="Nodes" class="org.springframework.aop.framework.ProxyFactoryBean">
|
<bean id="Nodes" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||||
|
@@ -25,11 +25,14 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.rest.api;
|
package org.alfresco.rest.api;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.rest.api.model.Document;
|
import org.alfresco.rest.api.model.Document;
|
||||||
import org.alfresco.rest.api.model.Folder;
|
import org.alfresco.rest.api.model.Folder;
|
||||||
import org.alfresco.rest.api.model.Node;
|
import org.alfresco.rest.api.model.Node;
|
||||||
|
import org.alfresco.rest.framework.resource.content.BasicContentInfo;
|
||||||
|
import org.alfresco.rest.framework.resource.content.BinaryResource;
|
||||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
@@ -96,13 +99,14 @@ public interface Nodes
|
|||||||
void deleteNode(String nodeId);
|
void deleteNode(String nodeId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Create node(s) - folder or (empty) file
|
||||||
*
|
*
|
||||||
* @param parentFolderNodeId
|
* @param parentFolderNodeId
|
||||||
* @param folderInfo
|
* @param nodeInfo
|
||||||
* @param parameters
|
* @param parameters
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
Folder createFolder(String parentFolderNodeId, Folder folderInfo, Parameters parameters);
|
Node createNode(String parentFolderNodeId, Node nodeInfo, Parameters parameters);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -112,4 +116,10 @@ public interface Nodes
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
Node updateNode(String nodeId, Node entity, Parameters parameters);
|
Node updateNode(String nodeId, Node entity, Parameters parameters);
|
||||||
|
|
||||||
|
// TODO update REST fwk - to optionally support "attachment" (Content-Disposition) header
|
||||||
|
BinaryResource getContent(String fileNodeId, Parameters parameters);
|
||||||
|
|
||||||
|
// TODO update REST fwk - to optionally support return of json
|
||||||
|
void updateContent(String fileNodeId, BasicContentInfo contentInfo, InputStream stream, Parameters parameters);
|
||||||
}
|
}
|
||||||
|
@@ -25,40 +25,57 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.rest.api.impl;
|
package org.alfresco.rest.api.impl;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.query.PagingRequest;
|
||||||
|
import org.alfresco.query.PagingResults;
|
||||||
|
import org.alfresco.repo.model.Repository;
|
||||||
|
import org.alfresco.repo.node.getchildren.GetChildrenCannedQuery;
|
||||||
|
import org.alfresco.rest.antlr.WhereClauseParser;
|
||||||
|
import org.alfresco.rest.api.Nodes;
|
||||||
|
import org.alfresco.rest.api.model.Document;
|
||||||
|
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.framework.core.exceptions.EntityNotFoundException;
|
||||||
|
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||||
|
import org.alfresco.rest.framework.resource.content.BasicContentInfo;
|
||||||
|
import org.alfresco.rest.framework.resource.content.BinaryResource;
|
||||||
|
import org.alfresco.rest.framework.resource.content.NodeBinaryResource;
|
||||||
|
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||||
|
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||||
|
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||||
|
import org.alfresco.rest.framework.resource.parameters.SortColumn;
|
||||||
|
import org.alfresco.rest.framework.resource.parameters.where.Query;
|
||||||
|
import org.alfresco.rest.framework.resource.parameters.where.QueryHelper;
|
||||||
|
import org.alfresco.rest.workflow.api.impl.MapBasedQueryWalker;
|
||||||
|
import org.alfresco.service.ServiceRegistry;
|
||||||
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
|
import org.alfresco.service.cmr.model.FileInfo;
|
||||||
|
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
|
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
|
import org.alfresco.service.cmr.security.AccessStatus;
|
||||||
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.AbstractList;
|
import java.util.AbstractList;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
|
||||||
import org.alfresco.opencmis.CMISConnector;
|
|
||||||
import org.alfresco.query.PagingRequest;
|
|
||||||
import org.alfresco.query.PagingResults;
|
|
||||||
import org.alfresco.repo.model.Repository;
|
|
||||||
import org.alfresco.rest.api.Nodes;
|
|
||||||
import org.alfresco.rest.api.model.Document;
|
|
||||||
import org.alfresco.rest.api.model.Folder;
|
|
||||||
import org.alfresco.rest.api.model.Node;
|
|
||||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
|
||||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
|
||||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
|
||||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
|
||||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
|
||||||
import org.alfresco.service.cmr.model.FileFolderService;
|
|
||||||
import org.alfresco.service.cmr.model.FileInfo;
|
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
|
||||||
import org.alfresco.service.cmr.repository.NodeService;
|
|
||||||
import org.alfresco.service.cmr.repository.Path.Element;
|
|
||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
|
||||||
import org.alfresco.service.cmr.security.PermissionService;
|
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
|
||||||
import org.alfresco.service.namespace.QName;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Centralises access to file/folder/node services and maps between representations.
|
* Centralises access to file/folder/node services and maps between representations.
|
||||||
*
|
*
|
||||||
@@ -77,33 +94,24 @@ public class NodesImpl implements Nodes
|
|||||||
|
|
||||||
private final static String PATH_ROOT = "-root-";
|
private final static String PATH_ROOT = "-root-";
|
||||||
private final static String PATH_MY = "-my-";
|
private final static String PATH_MY = "-my-";
|
||||||
|
private final static String PATH_SHARED = "-shared-";
|
||||||
|
|
||||||
private NodeService nodeService;
|
private NodeService nodeService;
|
||||||
private DictionaryService dictionaryService;
|
private DictionaryService dictionaryService;
|
||||||
private CMISConnector cmisConnector;
|
|
||||||
private FileFolderService fileFolderService;
|
private FileFolderService fileFolderService;
|
||||||
private Repository repositoryHelper;
|
|
||||||
private NamespaceService namespaceService;
|
private NamespaceService namespaceService;
|
||||||
private PermissionService permissionService;
|
private PermissionService permissionService;
|
||||||
|
private Repository repositoryHelper;
|
||||||
|
private ServiceRegistry sr;
|
||||||
|
|
||||||
public void setDictionaryService(DictionaryService dictionaryService)
|
public void setServiceRegistry(ServiceRegistry sr) {
|
||||||
{
|
this.sr = sr;
|
||||||
this.dictionaryService = dictionaryService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNodeService(NodeService nodeService)
|
this.namespaceService = sr.getNamespaceService();
|
||||||
{
|
this.fileFolderService = sr.getFileFolderService();
|
||||||
this.nodeService = nodeService;
|
this.nodeService = sr.getNodeService();
|
||||||
}
|
this.permissionService = sr.getPermissionService();
|
||||||
|
this.dictionaryService = sr.getDictionaryService();
|
||||||
public void setCmisConnector(CMISConnector cmisConnector)
|
|
||||||
{
|
|
||||||
this.cmisConnector = cmisConnector;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFileFolderService(FileFolderService fileFolderService)
|
|
||||||
{
|
|
||||||
this.fileFolderService = fileFolderService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRepositoryHelper(Repository repositoryHelper)
|
public void setRepositoryHelper(Repository repositoryHelper)
|
||||||
@@ -111,15 +119,59 @@ public class NodesImpl implements Nodes
|
|||||||
this.repositoryHelper = repositoryHelper;
|
this.repositoryHelper = repositoryHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNamespaceService(NamespaceService namespaceService)
|
private static final List<QName> EXCLUDED_ASPECTS = Arrays.asList(
|
||||||
{
|
ContentModel.ASPECT_REFERENCEABLE,
|
||||||
this.namespaceService = namespaceService;
|
ContentModel.ASPECT_LOCALIZED);
|
||||||
|
|
||||||
|
private static final List<QName> EXCLUDED_PROPS = Arrays.asList(
|
||||||
|
// top-level basic info
|
||||||
|
ContentModel.PROP_NAME,
|
||||||
|
ContentModel.PROP_MODIFIER,
|
||||||
|
ContentModel.PROP_MODIFIED,
|
||||||
|
ContentModel.PROP_CREATOR,
|
||||||
|
ContentModel.PROP_CREATED,
|
||||||
|
ContentModel.PROP_CONTENT,
|
||||||
|
// sys:localized
|
||||||
|
ContentModel.PROP_LOCALE,
|
||||||
|
// sys:referenceable
|
||||||
|
ContentModel.PROP_NODE_UUID,
|
||||||
|
ContentModel.PROP_STORE_IDENTIFIER,
|
||||||
|
ContentModel.PROP_STORE_PROTOCOL,
|
||||||
|
ContentModel.PROP_NODE_DBID,
|
||||||
|
// other - TBC
|
||||||
|
ContentModel.PROP_INITIAL_VERSION,
|
||||||
|
ContentModel.PROP_AUTO_VERSION_PROPS,
|
||||||
|
ContentModel.PROP_AUTO_VERSION);
|
||||||
|
|
||||||
|
private final static String PARAM_ISFOLDER = "isFolder";
|
||||||
|
private final static String PARAM_NAME = "name";
|
||||||
|
private final static String PARAM_CREATEDAT = "createdAt";
|
||||||
|
private final static String PARAM_MODIFIEDAT = "modifiedAt";
|
||||||
|
private final static String PARAM_CREATEBYUSER = "createdByUser";
|
||||||
|
private final static String PARAM_MODIFIEDBYUSER = "modifiedByUser";
|
||||||
|
private final static String PARAM_MIMETYPE = "mimeType";
|
||||||
|
private final static String PARAM_SIZEINBYTES = "sizeInBytes";
|
||||||
|
private final static String PARAM_NODETYPE = "nodeType";
|
||||||
|
|
||||||
|
private final static Map<String,QName> MAP_PARAM_QNAME;
|
||||||
|
static {
|
||||||
|
Map<String,QName> aMap = new HashMap<>(9);
|
||||||
|
|
||||||
|
aMap.put(PARAM_ISFOLDER, GetChildrenCannedQuery.SORT_QNAME_NODE_IS_FOLDER);
|
||||||
|
aMap.put(PARAM_NAME, ContentModel.PROP_NAME);
|
||||||
|
aMap.put(PARAM_CREATEDAT, ContentModel.PROP_CREATED);
|
||||||
|
aMap.put(PARAM_MODIFIEDAT, ContentModel.PROP_MODIFIED);
|
||||||
|
aMap.put(PARAM_CREATEBYUSER, ContentModel.PROP_CREATOR);
|
||||||
|
aMap.put(PARAM_MODIFIEDBYUSER, ContentModel.PROP_MODIFIER);
|
||||||
|
aMap.put(PARAM_MIMETYPE, GetChildrenCannedQuery.SORT_QNAME_CONTENT_MIMETYPE);
|
||||||
|
aMap.put(PARAM_SIZEINBYTES, GetChildrenCannedQuery.SORT_QNAME_CONTENT_SIZE);
|
||||||
|
aMap.put(PARAM_NODETYPE, GetChildrenCannedQuery.SORT_QNAME_NODE_TYPE);
|
||||||
|
|
||||||
|
MAP_PARAM_QNAME = Collections.unmodifiableMap(aMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPermissionService(PermissionService permissionService)
|
private final static Set<String> LIST_FOLDER_CHILDREN_EQUALS_QUERY_PROPERTIES =
|
||||||
{
|
new HashSet<>(Arrays.asList(new String[] {PARAM_ISFOLDER}));
|
||||||
this.permissionService = permissionService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
@@ -167,9 +219,12 @@ public class NodesImpl implements Nodes
|
|||||||
throw new EntityNotFoundException(nodeRef.getId());
|
throw new EntityNotFoundException(nodeRef.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
QName type = nodeService.getType(nodeRef);
|
return typeMatches(nodeService.getType(nodeRef), expectedTypes, excludedTypes);
|
||||||
|
}
|
||||||
|
|
||||||
Set<QName> allExpectedTypes = new HashSet<QName>();
|
protected boolean typeMatches(QName type, Set<QName> expectedTypes, Set<QName> excludedTypes)
|
||||||
|
{
|
||||||
|
Set<QName> allExpectedTypes = new HashSet<>();
|
||||||
if (expectedTypes != null)
|
if (expectedTypes != null)
|
||||||
{
|
{
|
||||||
for (QName expectedType : expectedTypes)
|
for (QName expectedType : expectedTypes)
|
||||||
@@ -178,7 +233,7 @@ public class NodesImpl implements Nodes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<QName> allExcludedTypes = new HashSet<QName>();
|
Set<QName> allExcludedTypes = new HashSet<>();
|
||||||
if (excludedTypes != null)
|
if (excludedTypes != null)
|
||||||
{
|
{
|
||||||
for (QName excludedType : excludedTypes)
|
for (QName excludedType : excludedTypes)
|
||||||
@@ -192,16 +247,22 @@ public class NodesImpl implements Nodes
|
|||||||
return(inExpected && !excluded);
|
return(inExpected && !excluded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated review usage (backward compat')
|
||||||
|
*/
|
||||||
public Node getNode(String nodeId)
|
public Node getNode(String nodeId)
|
||||||
{
|
{
|
||||||
NodeRef nodeRef = validateNode(nodeId);
|
NodeRef nodeRef = validateNode(nodeId);
|
||||||
|
|
||||||
return new Node(nodeRef, nodeService.getProperties(nodeRef), namespaceService);
|
return new Node(nodeRef, null, nodeService.getProperties(nodeRef), sr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated review usage (backward compat')
|
||||||
|
*/
|
||||||
public Node getNode(NodeRef nodeRef)
|
public Node getNode(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
return new Node(nodeRef, nodeService.getProperties(nodeRef), namespaceService);
|
return new Node(nodeRef, null, nodeService.getProperties(nodeRef), sr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Type getType(NodeRef nodeRef)
|
private Type getType(NodeRef nodeRef)
|
||||||
@@ -216,65 +277,19 @@ public class NodesImpl implements Nodes
|
|||||||
return isContainer ? Type.FOLDER : Type.DOCUMENT;
|
return isContainer ? Type.FOLDER : Type.DOCUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// TODO filter CMIS properties
|
|
||||||
// TODO review & optimise - do we really need to go via CMIS properties !?
|
|
||||||
private Properties getCMISProperties(NodeRef nodeRef)
|
|
||||||
{
|
|
||||||
CMISNodeInfoImpl nodeInfo = cmisConnector.createNodeInfo(nodeRef);
|
|
||||||
final Properties properties = cmisConnector.getNodeProperties(nodeInfo, null);
|
|
||||||
|
|
||||||
// fake the title property, which CMIS doesn't give us
|
|
||||||
String title = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_TITLE);
|
|
||||||
final PropertyStringImpl titleProp = new PropertyStringImpl(ContentModel.PROP_TITLE.toString(), title);
|
|
||||||
Properties wrapProperties = new Properties()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public List<CmisExtensionElement> getExtensions()
|
|
||||||
{
|
|
||||||
return properties.getExtensions();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setExtensions(List<CmisExtensionElement> extensions)
|
|
||||||
{
|
|
||||||
properties.setExtensions(extensions);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, PropertyData<?>> getProperties()
|
|
||||||
{
|
|
||||||
Map<String, PropertyData<?>> updatedProperties = new HashMap<String, PropertyData<?>>(properties.getProperties());
|
|
||||||
updatedProperties.put(titleProp.getId(), titleProp);
|
|
||||||
return updatedProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<PropertyData<?>> getPropertyList()
|
|
||||||
{
|
|
||||||
List<PropertyData<?>> propertyList = new ArrayList<PropertyData<?>>(properties.getPropertyList());
|
|
||||||
propertyList.add(titleProp);
|
|
||||||
return propertyList;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return wrapProperties;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the public api representation of a document.
|
* Returns the public api representation of a document.
|
||||||
*
|
*
|
||||||
* Note: properties are modelled after the OpenCMIS node properties
|
* @deprecated review usage (backward compat')
|
||||||
*/
|
*/
|
||||||
public Document getDocument(NodeRef nodeRef)
|
public Document getDocument(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
Type type = getType(nodeRef);
|
Type type = getType(nodeRef);
|
||||||
if (type.equals(Type.DOCUMENT))
|
if (type.equals(Type.DOCUMENT))
|
||||||
{
|
{
|
||||||
//Properties properties = getCMISProperties(nodeRef);
|
|
||||||
Map<QName, Serializable> properties = nodeService.getProperties(nodeRef);
|
Map<QName, Serializable> properties = nodeService.getProperties(nodeRef);
|
||||||
Document doc = new Document(nodeRef, properties, namespaceService);
|
|
||||||
|
Document doc = new Document(nodeRef, getParentNodeRef(nodeRef), properties, sr);
|
||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -286,16 +301,16 @@ public class NodesImpl implements Nodes
|
|||||||
/**
|
/**
|
||||||
* Returns the public api representation of a folder.
|
* Returns the public api representation of a folder.
|
||||||
*
|
*
|
||||||
* Note: properties are modelled after the OpenCMIS node properties
|
* @deprecated review usage (backward compat')
|
||||||
*/
|
*/
|
||||||
public Folder getFolder(NodeRef nodeRef)
|
public Folder getFolder(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
Type type = getType(nodeRef);
|
Type type = getType(nodeRef);
|
||||||
if (type.equals(Type.FOLDER))
|
if (type.equals(Type.FOLDER))
|
||||||
{
|
{
|
||||||
//Properties properties = getCMISProperties(nodeRef);
|
|
||||||
Map<QName, Serializable> properties = nodeService.getProperties(nodeRef);
|
Map<QName, Serializable> properties = nodeService.getProperties(nodeRef);
|
||||||
Folder folder = new Folder(nodeRef, properties, namespaceService);
|
|
||||||
|
Folder folder = new Folder(nodeRef, getParentNodeRef(nodeRef), properties, sr);
|
||||||
return folder;
|
return folder;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -304,12 +319,27 @@ public class NodesImpl implements Nodes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private NodeRef getParentNodeRef(final NodeRef nodeRef) {
|
||||||
|
|
||||||
|
if (repositoryHelper.getCompanyHome().equals(nodeRef))
|
||||||
|
{
|
||||||
|
return null; // note: does not make sense to return parent above C/H
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodeService.getPrimaryParent(nodeRef).getParentRef();
|
||||||
|
}
|
||||||
|
|
||||||
private NodeRef validateOrLookupNode(String nodeId, String path) {
|
private NodeRef validateOrLookupNode(String nodeId, String path) {
|
||||||
final NodeRef parentNodeRef;
|
NodeRef parentNodeRef;
|
||||||
|
|
||||||
if (nodeId.equals(PATH_ROOT))
|
if (nodeId.equals(PATH_ROOT))
|
||||||
{
|
{
|
||||||
parentNodeRef = repositoryHelper.getCompanyHome();
|
parentNodeRef = repositoryHelper.getCompanyHome();
|
||||||
}
|
}
|
||||||
|
else if (nodeId.equals(PATH_SHARED))
|
||||||
|
{
|
||||||
|
parentNodeRef = repositoryHelper.getSharedHome();
|
||||||
|
}
|
||||||
else if (nodeId.equals(PATH_MY))
|
else if (nodeId.equals(PATH_MY))
|
||||||
{
|
{
|
||||||
NodeRef person = repositoryHelper.getPerson();
|
NodeRef person = repositoryHelper.getPerson();
|
||||||
@@ -323,103 +353,272 @@ public class NodesImpl implements Nodes
|
|||||||
{
|
{
|
||||||
parentNodeRef = validateNode(nodeId);
|
parentNodeRef = validateNode(nodeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (path != null) {
|
||||||
|
// resolve path relative to current nodeId
|
||||||
|
parentNodeRef = resolveNodeByPath(parentNodeRef, path, true);
|
||||||
|
}
|
||||||
|
|
||||||
return parentNodeRef;
|
return parentNodeRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected NodeRef resolveNodeByPath(final NodeRef parentNodeRef, String path, boolean checkForCompanyHome)
|
||||||
|
{
|
||||||
|
final List<String> pathElements = new ArrayList<>(0);
|
||||||
|
|
||||||
|
if ((path != null) && (! path.isEmpty())) {
|
||||||
|
|
||||||
|
if (path.startsWith("/")) {
|
||||||
|
path = path.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! path.isEmpty()) {
|
||||||
|
pathElements.addAll(Arrays.asList(path.split("/")));
|
||||||
|
|
||||||
|
if (checkForCompanyHome)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
if (nodeService.getRootNode(parentNodeRef.getStoreRef()).equals(parentNodeRef)) {
|
||||||
|
// special case
|
||||||
|
NodeRef chNodeRef = repositoryHelper.getCompanyHome();
|
||||||
|
String chName = (String)nodeService.getProperty(chNodeRef, ContentModel.PROP_NAME);
|
||||||
|
if (chName.equals(pathElements.get(0))) {
|
||||||
|
pathElements = pathElements.subList(1, pathElements.size());
|
||||||
|
parentNodeRef = chNodeRef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileInfo fileInfo = null;
|
||||||
|
try {
|
||||||
|
if (pathElements.size() != 0) {
|
||||||
|
fileInfo = fileFolderService.resolveNamePath(parentNodeRef, pathElements);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fileInfo = fileFolderService.getFileInfo(parentNodeRef);
|
||||||
|
if (fileInfo == null)
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException(parentNodeRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException fnfe) {
|
||||||
|
// convert checked exception
|
||||||
|
throw new InvalidNodeRefException(fnfe.getMessage()+" ["+path+"]", parentNodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileInfo.getNodeRef();
|
||||||
|
}
|
||||||
|
|
||||||
public Node getFolderOrDocument(String nodeId, Parameters parameters)
|
public Node getFolderOrDocument(String nodeId, Parameters parameters)
|
||||||
{
|
{
|
||||||
String path = parameters.getParameter("path");
|
String path = parameters.getParameter("path");
|
||||||
|
|
||||||
boolean incPrimaryPath = false;
|
|
||||||
String str = parameters.getParameter("incPrimaryPath");
|
|
||||||
if (str != null) {
|
|
||||||
incPrimaryPath = new Boolean(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeRef nodeRef = validateOrLookupNode(nodeId, path);
|
NodeRef nodeRef = validateOrLookupNode(nodeId, path);
|
||||||
|
|
||||||
QName typeQName = nodeService.getType(nodeRef);
|
QName typeQName = nodeService.getType(nodeRef);
|
||||||
return getFolderOrDocument(nodeRef, typeQName, incPrimaryPath);
|
return getFolderOrDocument(nodeRef, getParentNodeRef(nodeRef), typeQName, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Node getFolderOrDocument(NodeRef nodeRef, QName typeQName,boolean incPrimaryPath)
|
private Node getFolderOrDocument(final NodeRef nodeRef, NodeRef parentNodeRef, QName typeQName, boolean minimalnfo)
|
||||||
{
|
{
|
||||||
String primaryPath = null;
|
PathInfo pathInfo = null;
|
||||||
if (incPrimaryPath)
|
if (! minimalnfo)
|
||||||
{
|
{
|
||||||
org.alfresco.service.cmr.repository.Path pp = nodeService.getPath(nodeRef);
|
pathInfo = lookupPathInfo(nodeRef);
|
||||||
|
|
||||||
// Remove "app:company_home" (2nd element)
|
|
||||||
int ppSize = pp.size();
|
|
||||||
if (ppSize > 1) {
|
|
||||||
if (ppSize == 2) {
|
|
||||||
pp = pp.subPath(0, 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Element rootElement = pp.get(0);
|
|
||||||
pp = pp.subPath(2, ppSize-1).prepend(rootElement);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
primaryPath = pp.toDisplayPath(nodeService, permissionService); // note: slower (hence optional when getting node info)
|
|
||||||
}
|
|
||||||
|
|
||||||
Node node = null;
|
|
||||||
Type type = getType(typeQName);
|
Type type = getType(typeQName);
|
||||||
|
|
||||||
|
Node node;
|
||||||
Map<QName, Serializable> properties = nodeService.getProperties(nodeRef);
|
Map<QName, Serializable> properties = nodeService.getProperties(nodeRef);
|
||||||
|
|
||||||
if (type.equals(Type.DOCUMENT))
|
if (type.equals(Type.DOCUMENT))
|
||||||
{
|
{
|
||||||
//Properties properties = getCMISProperties(nodeRef);
|
node = new Document(nodeRef, parentNodeRef, properties, sr);
|
||||||
node = new Document(nodeRef, properties, namespaceService);
|
|
||||||
}
|
}
|
||||||
else if (type.equals(Type.FOLDER))
|
else if (type.equals(Type.FOLDER))
|
||||||
{
|
{
|
||||||
// container/folder
|
// container/folder
|
||||||
//Properties properties = getCMISProperties(nodeRef);
|
node = new Folder(nodeRef, parentNodeRef, properties, sr);
|
||||||
node = new Folder(nodeRef, properties, namespaceService);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new InvalidArgumentException("Node is not a folder or file");
|
throw new InvalidArgumentException("Node is not a folder or file");
|
||||||
}
|
}
|
||||||
|
|
||||||
node.setType(typeQName.toPrefixString(namespaceService));
|
if (! minimalnfo) {
|
||||||
node.setPrimaryPath(primaryPath); // optional - can be null
|
node.setProperties(mapProperties(properties));
|
||||||
|
node.setAspectNames(mapAspects(nodeService.getAspects(nodeRef)));
|
||||||
|
}
|
||||||
|
|
||||||
|
node.setNodeType(typeQName.toPrefixString(namespaceService));
|
||||||
|
node.setPath(pathInfo);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected PathInfo lookupPathInfo(NodeRef nodeRefIn)
|
||||||
|
{
|
||||||
|
List<PathInfo.ElementInfo> elements = new ArrayList<>(5);
|
||||||
|
|
||||||
|
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
|
||||||
|
boolean isComplete = true;
|
||||||
|
|
||||||
|
NodeRef pNodeRef = nodeRefIn;
|
||||||
|
while (pNodeRef != null)
|
||||||
|
{
|
||||||
|
if (pNodeRef.equals(companyHomeNodeRef))
|
||||||
|
{
|
||||||
|
pNodeRef = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pNodeRef = nodeService.getPrimaryParent(pNodeRef).getParentRef();
|
||||||
|
|
||||||
|
if (pNodeRef == null)
|
||||||
|
{
|
||||||
|
// belts-and-braces - is it even possible to get here ?
|
||||||
|
isComplete = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (permissionService.hasPermission(pNodeRef, PermissionService.READ) == AccessStatus.ALLOWED)
|
||||||
|
{
|
||||||
|
String name = (String) nodeService.getProperty(pNodeRef, ContentModel.PROP_NAME);
|
||||||
|
elements.add(0, new PathInfo().new ElementInfo(pNodeRef.getId(), name));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isComplete = false;
|
||||||
|
pNodeRef = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (PathInfo.ElementInfo e : elements)
|
||||||
|
{
|
||||||
|
sb.append("/").append(e.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PathInfo(sb.toString(), isComplete, elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Map<String, Serializable> mapProperties(Map<QName, Serializable> nodeProps)
|
||||||
|
{
|
||||||
|
Map<String, Serializable> props = new HashMap<>(nodeProps.size());
|
||||||
|
|
||||||
|
for (Map.Entry<QName, Serializable> entry : nodeProps.entrySet()) {
|
||||||
|
QName propQName = entry.getKey();
|
||||||
|
if (!EXCLUDED_PROPS.contains(propQName))
|
||||||
|
{
|
||||||
|
props.put(entry.getKey().toPrefixString(namespaceService), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.size() == 0)
|
||||||
|
{
|
||||||
|
props = null; // no props to return
|
||||||
|
}
|
||||||
|
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<String> mapAspects(Set<QName> nodeAspects)
|
||||||
|
{
|
||||||
|
List<String> aspectNames = new ArrayList<>(nodeAspects.size());
|
||||||
|
|
||||||
|
for (QName aspectName : nodeAspects)
|
||||||
|
{
|
||||||
|
if (! EXCLUDED_ASPECTS.contains(aspectName))
|
||||||
|
{
|
||||||
|
aspectNames.add(aspectName.toPrefixString(namespaceService));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aspectNames.size() == 0)
|
||||||
|
{
|
||||||
|
aspectNames = null; // no aspects to return
|
||||||
|
}
|
||||||
|
|
||||||
|
return aspectNames;
|
||||||
|
}
|
||||||
|
|
||||||
public CollectionWithPagingInfo<Node> getChildren(String parentFolderNodeId, Parameters parameters)
|
public CollectionWithPagingInfo<Node> getChildren(String parentFolderNodeId, Parameters parameters)
|
||||||
{
|
{
|
||||||
// TODO consider using: where=(exists(target/file)) / where=(exists(target/file))
|
// TODO
|
||||||
// instead of: includeFiles=true / includeFolders=true
|
// map - where (filter) properties - including isFolder
|
||||||
|
// map - orderBy (sort) properties - including isFolder
|
||||||
|
|
||||||
|
// TODO refactor & fix !
|
||||||
|
final boolean minimalnfo = (parameters.getSelectedProperties().size() == 0);
|
||||||
|
|
||||||
boolean includeFolders = true;
|
boolean includeFolders = true;
|
||||||
String str = parameters.getParameter("includeFolders");
|
|
||||||
if (str != null) {
|
|
||||||
includeFolders = new Boolean(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean includeFiles = true;
|
boolean includeFiles = true;
|
||||||
str = parameters.getParameter("includeFiles");
|
|
||||||
if (str != null) {
|
Query q = parameters.getQuery();
|
||||||
includeFiles = new Boolean(str);
|
|
||||||
|
if (q != null)
|
||||||
|
{
|
||||||
|
// TODO confirm list of filter props - what about custom props (+ across types/aspects) ?
|
||||||
|
MapBasedQueryWalker propertyWalker = new MapBasedQueryWalker(LIST_FOLDER_CHILDREN_EQUALS_QUERY_PROPERTIES, null);
|
||||||
|
QueryHelper.walk(q, propertyWalker);
|
||||||
|
|
||||||
|
Boolean b = propertyWalker.getProperty(PARAM_ISFOLDER, WhereClauseParser.EQUALS, Boolean.class);
|
||||||
|
if (b != null)
|
||||||
|
{
|
||||||
|
includeFiles = !b;
|
||||||
|
includeFolders = b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String path = parameters.getParameter("path");
|
List<SortColumn> sortCols = parameters.getSorting();
|
||||||
|
List<Pair<QName, Boolean>> sortProps = null;
|
||||||
|
if ((sortCols != null) && (sortCols.size() > 0))
|
||||||
|
{
|
||||||
|
sortProps = new ArrayList<>(sortCols.size());
|
||||||
|
for (SortColumn sortCol : sortCols)
|
||||||
|
{
|
||||||
|
QName propQname = MAP_PARAM_QNAME.get(sortCol.column);
|
||||||
|
if (propQname == null)
|
||||||
|
{
|
||||||
|
propQname = QName.resolveToQName(namespaceService, sortCol.column);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propQname != null)
|
||||||
|
{
|
||||||
|
sortProps.add(new Pair<>(propQname, sortCol.asc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// default sort order
|
||||||
|
sortProps = new ArrayList<>(Arrays.asList(
|
||||||
|
new Pair<>(GetChildrenCannedQuery.SORT_QNAME_NODE_IS_FOLDER, Boolean.FALSE),
|
||||||
|
new Pair<>(ContentModel.PROP_NAME, true)));
|
||||||
|
}
|
||||||
|
|
||||||
Paging paging = parameters.getPaging();
|
Paging paging = parameters.getPaging();
|
||||||
|
|
||||||
|
// TODO do we want to support path with list folder children ?
|
||||||
|
String path = null;
|
||||||
|
//String path = parameters.getParameter("path");
|
||||||
|
|
||||||
final NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, path);
|
final NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, path);
|
||||||
|
|
||||||
final Set<QName> folders = new HashSet<>(Arrays.asList(ContentModel.TYPE_FOLDER));
|
if (! nodeMatches(parentNodeRef, Collections.singleton(ContentModel.TYPE_FOLDER), null))
|
||||||
if (! nodeMatches(parentNodeRef, folders, null))
|
|
||||||
{
|
{
|
||||||
throw new InvalidArgumentException("NodeId of folder is expected");
|
throw new InvalidArgumentException("NodeId of folder is expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
PagingRequest pagingRequest = Util.getPagingRequest(paging);
|
PagingRequest pagingRequest = Util.getPagingRequest(paging);
|
||||||
|
|
||||||
final PagingResults<FileInfo> pagingResults = fileFolderService.list(parentNodeRef, includeFiles, includeFolders, null, null, pagingRequest);
|
final PagingResults<FileInfo> pagingResults = fileFolderService.list(parentNodeRef, includeFiles, includeFolders, null, sortProps, pagingRequest);
|
||||||
|
|
||||||
final List<FileInfo> page = pagingResults.getPage();
|
final List<FileInfo> page = pagingResults.getPage();
|
||||||
List<Node> nodes = new AbstractList<Node>()
|
List<Node> nodes = new AbstractList<Node>()
|
||||||
@@ -428,7 +627,9 @@ public class NodesImpl implements Nodes
|
|||||||
public Node get(int index)
|
public Node get(int index)
|
||||||
{
|
{
|
||||||
FileInfo fInfo = page.get(index);
|
FileInfo fInfo = page.get(index);
|
||||||
return getFolderOrDocument(fInfo.getNodeRef(), fInfo.getType(), false);
|
|
||||||
|
// basic info by default (unless "select"ed otherwise)
|
||||||
|
return getFolderOrDocument(fInfo.getNodeRef(), parentNodeRef, fInfo.getType(), minimalnfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -447,48 +648,68 @@ public class NodesImpl implements Nodes
|
|||||||
fileFolderService.delete(nodeRef);
|
fileFolderService.delete(nodeRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Folder createFolder(String parentFolderNodeId, Folder folderInfo, Parameters parameters)
|
// TODO should we able to specify content properties (eg. mimeType ... or use extension for now, or encoding)
|
||||||
|
public Node createNode(String parentFolderNodeId, Node nodeInfo, Parameters parameters)
|
||||||
{
|
{
|
||||||
final NodeRef parentNodeRef = validateNode(parentFolderNodeId);
|
// check that requested parent node exists and it's type is a (sub-)type of folder
|
||||||
|
final NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, null);
|
||||||
|
|
||||||
final Set<QName> folders = new HashSet<>(Arrays.asList(ContentModel.TYPE_FOLDER));
|
if (! nodeMatches(parentNodeRef, Collections.singleton(ContentModel.TYPE_FOLDER), null))
|
||||||
if (! nodeMatches(parentNodeRef, folders, null))
|
|
||||||
{
|
{
|
||||||
throw new InvalidArgumentException("NodeId of folder is expected");
|
throw new InvalidArgumentException("NodeId of folder is expected: "+parentNodeRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
String folderName = folderInfo.getName();
|
String nodeName = nodeInfo.getName();
|
||||||
String folderType = folderInfo.getType();
|
if ((nodeName == null) || nodeName.isEmpty())
|
||||||
if (folderType == null) {
|
{
|
||||||
folderType = "cm:folder";
|
throw new InvalidArgumentException("Node name is expected: "+parentNodeRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
QName folderTypeQName = QName.resolveToQName(namespaceService, folderType);
|
String nodeType = nodeInfo.getNodeType();
|
||||||
|
if ((nodeType == null) || nodeType.isEmpty())
|
||||||
Map<QName, Serializable> props = new HashMap<QName, Serializable>(10);
|
{
|
||||||
|
throw new InvalidArgumentException("Node type is expected: "+parentNodeRef+","+nodeName);
|
||||||
props.put(ContentModel.PROP_NAME, folderName);
|
|
||||||
|
|
||||||
String title = folderInfo.getTitle();
|
|
||||||
if ((title != null) && (! title.isEmpty())) {
|
|
||||||
props.put(ContentModel.PROP_TITLE, title);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String description = folderInfo.getDescription();
|
// check that requested type is a (sub-) type of folder or content
|
||||||
if ((description != null) && (! description.isEmpty())) {
|
QName nodeTypeQName = QName.resolveToQName(namespaceService, nodeType);
|
||||||
props.put(ContentModel.PROP_DESCRIPTION, description);
|
|
||||||
|
Set<QName> contentAndFolders = new HashSet<>(Arrays.asList(ContentModel.TYPE_FOLDER, ContentModel.TYPE_CONTENT));
|
||||||
|
if (! typeMatches(nodeTypeQName, contentAndFolders, null)) {
|
||||||
|
throw new InvalidArgumentException("Type of folder or content is expected: "+ nodeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO other custom properties !!
|
boolean isContent = typeMatches(nodeTypeQName, Collections.singleton(ContentModel.TYPE_CONTENT), null);
|
||||||
|
|
||||||
QName assocQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(folderName));
|
Map<QName, Serializable> props = new HashMap<>(10);
|
||||||
|
|
||||||
NodeRef nodeRef = nodeService.createNode(parentNodeRef, ContentModel.ASSOC_CONTAINS, assocQName, folderTypeQName, props).getChildRef();
|
if (nodeInfo.getProperties() != null)
|
||||||
|
{
|
||||||
return (Folder) getFolderOrDocument(nodeRef.getId(), parameters);
|
for (Map.Entry entry : (Set<Map.Entry<String, Serializable>>)nodeInfo.getProperties().entrySet())
|
||||||
|
{
|
||||||
|
QName propQName = QName.createQName((String)entry.getKey(), namespaceService);
|
||||||
|
props.put(propQName, (Serializable)entry.getValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Node updateNode(String nodeId, Node nodeInfo, Parameters parameters) {
|
props.put(ContentModel.PROP_NAME, nodeName);
|
||||||
|
|
||||||
|
QName assocQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(nodeName));
|
||||||
|
NodeRef nodeRef = nodeService.createNode(parentNodeRef, ContentModel.ASSOC_CONTAINS, assocQName, nodeTypeQName, props).getChildRef();
|
||||||
|
|
||||||
|
if (isContent) {
|
||||||
|
// add empty file
|
||||||
|
ContentWriter writer = sr.getContentService().getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
|
||||||
|
String mimeType = sr.getMimetypeService().guessMimetype(nodeName);
|
||||||
|
writer.setMimetype(mimeType);
|
||||||
|
writer.putContent("");
|
||||||
|
}
|
||||||
|
|
||||||
|
return getFolderOrDocument(nodeRef.getId(), parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node updateNode(String nodeId, Node nodeInfo, Parameters parameters)
|
||||||
|
{
|
||||||
|
|
||||||
final NodeRef nodeRef = validateNode(nodeId);
|
final NodeRef nodeRef = validateNode(nodeId);
|
||||||
|
|
||||||
@@ -500,26 +721,72 @@ public class NodesImpl implements Nodes
|
|||||||
|
|
||||||
Map<QName, Serializable> props = new HashMap<>(10);
|
Map<QName, Serializable> props = new HashMap<>(10);
|
||||||
|
|
||||||
|
if (nodeInfo.getProperties() != null)
|
||||||
|
{
|
||||||
|
for (Map.Entry entry : (Set<Map.Entry<String, Serializable>>)nodeInfo.getProperties().entrySet())
|
||||||
|
{
|
||||||
|
QName propQName = QName.createQName((String)entry.getKey(), namespaceService);
|
||||||
|
props.put(propQName, (Serializable)entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String name = nodeInfo.getName();
|
String name = nodeInfo.getName();
|
||||||
if ((name != null) && (! name.isEmpty())) {
|
if ((name != null) && (! name.isEmpty()))
|
||||||
|
{
|
||||||
// note: this is equivalent of a rename within target folder
|
// note: this is equivalent of a rename within target folder
|
||||||
props.put(ContentModel.PROP_NAME, name);
|
props.put(ContentModel.PROP_NAME, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
String title = nodeInfo.getTitle();
|
if (props.size() > 0)
|
||||||
if ((title != null) && (! title.isEmpty())) {
|
{
|
||||||
props.put(ContentModel.PROP_TITLE, title);
|
|
||||||
}
|
|
||||||
|
|
||||||
String description = nodeInfo.getDescription();
|
|
||||||
if ((description != null) && (! description.isEmpty())) {
|
|
||||||
props.put(ContentModel.PROP_DESCRIPTION, description);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.size() > 0) {
|
|
||||||
nodeService.addProperties(nodeRef, props);
|
nodeService.addProperties(nodeRef, props);
|
||||||
}
|
}
|
||||||
|
|
||||||
return getFolderOrDocument(nodeRef.getId(), parameters);
|
return getFolderOrDocument(nodeRef.getId(), parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BinaryResource getContent(String fileNodeId, Parameters parameters)
|
||||||
|
{
|
||||||
|
final NodeRef nodeRef = validateNode(fileNodeId);
|
||||||
|
|
||||||
|
if (! nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null))
|
||||||
|
{
|
||||||
|
throw new InvalidArgumentException("NodeId of content is expected: "+nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO attachment header - update (or extend ?) REST fwk
|
||||||
|
return new NodeBinaryResource(nodeRef, ContentModel.PROP_CONTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateContent(String fileNodeId, BasicContentInfo contentInfo, InputStream stream, Parameters parameters)
|
||||||
|
{
|
||||||
|
final NodeRef nodeRef = validateNode(fileNodeId);
|
||||||
|
|
||||||
|
if (! nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null))
|
||||||
|
{
|
||||||
|
throw new InvalidArgumentException("NodeId of content is expected: "+nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentWriter writer = sr.getContentService().getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
|
||||||
|
|
||||||
|
String mimeType = contentInfo.getMimeType();
|
||||||
|
if (mimeType == null)
|
||||||
|
{
|
||||||
|
String fileName = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT);
|
||||||
|
writer.guessMimetype(fileName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.setMimetype(mimeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.guessEncoding();
|
||||||
|
|
||||||
|
writer.putContent(stream);
|
||||||
|
|
||||||
|
// TODO - hmm - we may wish to return json info !!
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
50
source/java/org/alfresco/rest/api/model/ContentInfo.java
Normal file
50
source/java/org/alfresco/rest/api/model/ContentInfo.java
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package org.alfresco.rest.api.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of content info
|
||||||
|
*
|
||||||
|
* @author janv
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ContentInfo
|
||||||
|
{
|
||||||
|
private String mimeType;
|
||||||
|
private String mimeTypeName;
|
||||||
|
private long sizeInBytes;
|
||||||
|
private String encoding;
|
||||||
|
|
||||||
|
public ContentInfo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentInfo( String mimeType, String mimeTypeName, long sizeInBytes, String encoding)
|
||||||
|
{
|
||||||
|
this.mimeType = mimeType;
|
||||||
|
this.mimeTypeName = mimeTypeName;
|
||||||
|
this.sizeInBytes = sizeInBytes;
|
||||||
|
this.encoding = encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMimeType() {
|
||||||
|
return mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMimeTypeName() {
|
||||||
|
return mimeTypeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSizeInBytes() {
|
||||||
|
return sizeInBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEncoding() {
|
||||||
|
return encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "ContentInfo [mimeType=" + mimeType + ", mimeTypeName=" + mimeTypeName
|
||||||
|
+ ", encoding=" + encoding + ", sizeInBytes=" + sizeInBytes + "]";
|
||||||
|
}
|
||||||
|
}
|
@@ -29,12 +29,11 @@ import java.io.Serializable;
|
|||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.service.ServiceRegistry;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentData;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.apache.chemistry.opencmis.commons.PropertyIds;
|
|
||||||
import org.apache.chemistry.opencmis.commons.data.Properties;
|
|
||||||
import org.apache.chemistry.opencmis.commons.data.PropertyData;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Representation of a document node.
|
* Representation of a document node.
|
||||||
@@ -45,30 +44,31 @@ import org.apache.chemistry.opencmis.commons.data.PropertyData;
|
|||||||
*/
|
*/
|
||||||
public class Document extends Node
|
public class Document extends Node
|
||||||
{
|
{
|
||||||
|
// TODO backward compat' - favourites etc
|
||||||
private String mimeType;
|
private String mimeType;
|
||||||
private BigInteger sizeInBytes;
|
private BigInteger sizeInBytes;
|
||||||
private String versionLabel;
|
private String versionLabel;
|
||||||
|
|
||||||
public Document()
|
private ContentInfo contentInfo;
|
||||||
{
|
|
||||||
|
public Document() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
public Document(NodeRef nodeRef, NodeRef parentNodeRef, Map<QName, Serializable> nodeProps, ServiceRegistry sr)
|
||||||
public Document(NodeRef nodeRef, Properties properties)
|
|
||||||
{
|
{
|
||||||
super(nodeRef, properties);
|
super(nodeRef, parentNodeRef, nodeProps, sr);
|
||||||
|
|
||||||
Map<String, PropertyData<?>> props = properties.getProperties();
|
Serializable val = nodeProps.get(ContentModel.PROP_CONTENT);
|
||||||
this.mimeType = (String)getValue(props, PropertyIds.CONTENT_STREAM_MIME_TYPE);
|
|
||||||
this.sizeInBytes = (BigInteger)getValue(props, PropertyIds.CONTENT_STREAM_LENGTH);
|
if ((val != null) && (val instanceof ContentData)) {
|
||||||
this.versionLabel = (String)getValue(props, PropertyIds.VERSION_LABEL);
|
ContentData cd = (ContentData)val;
|
||||||
|
String mimeType = cd.getMimetype();
|
||||||
|
String mimeTypeName = sr.getMimetypeService().getDisplaysByMimetype().get(mimeType);
|
||||||
|
this.contentInfo = new ContentInfo(mimeType, mimeTypeName, cd.getSize(), cd.getEncoding());
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
public Document(NodeRef nodeRef, Map<QName, Serializable> nodeProps, NamespaceService namespaceService)
|
//this.versionLabel = (String)nodeProps.get(ContentModel.PROP_VERSION_LABEL);
|
||||||
{
|
|
||||||
super(nodeRef, nodeProps, namespaceService);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMimeType()
|
public String getMimeType()
|
||||||
@@ -91,13 +91,16 @@ public class Document extends Node
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ContentInfo getContent()
|
||||||
|
{
|
||||||
|
return contentInfo;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return "Document [mimeType=" + mimeType + ", sizeInBytes="
|
return "Document [contentInfo=" + contentInfo.toString() + ", nodeRef="
|
||||||
+ sizeInBytes + ", versionLabel=" + versionLabel + ", nodeRef="
|
+ nodeRef + ", name=" + name + ", createdAt=" + createdAt
|
||||||
+ nodeRef + ", name=" + name + ", title=" + title
|
|
||||||
+ ", description=" + description + ", createdAt=" + createdAt
|
|
||||||
+ ", modifiedAt=" + modifiedAt + ", createdBy=" + createdBy
|
+ ", modifiedAt=" + modifiedAt + ", createdBy=" + createdBy
|
||||||
+ ", modifiedBy=" + modifiedBy + "]";
|
+ ", modifiedBy=" + modifiedBy + "]";
|
||||||
}
|
}
|
||||||
|
@@ -28,10 +28,9 @@ package org.alfresco.rest.api.model;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.service.ServiceRegistry;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.apache.chemistry.opencmis.commons.data.Properties;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Representation of a folder node.
|
* Representation of a folder node.
|
||||||
@@ -47,16 +46,9 @@ public class Folder extends Node
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
public Folder(NodeRef nodeRef, NodeRef parentNodeRef, Map<QName, Serializable> nodeProps, ServiceRegistry sr)
|
||||||
public Folder(NodeRef nodeRef, Properties properties)
|
|
||||||
{
|
{
|
||||||
super(nodeRef, properties);
|
super(nodeRef, parentNodeRef, nodeProps, sr);
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
public Folder(NodeRef nodeRef, Map<QName, Serializable> nodeProps, NamespaceService namespaceService)
|
|
||||||
{
|
|
||||||
super(nodeRef, nodeProps, namespaceService);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getIsFolder()
|
public Boolean getIsFolder()
|
||||||
|
@@ -26,23 +26,18 @@
|
|||||||
package org.alfresco.rest.api.model;
|
package org.alfresco.rest.api.model;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.GregorianCalendar;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
import org.alfresco.rest.framework.resource.UniqueId;
|
import org.alfresco.rest.framework.resource.UniqueId;
|
||||||
|
import org.alfresco.service.ServiceRegistry;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
import org.alfresco.service.cmr.security.PersonService;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.util.EqualsHelper;
|
import org.alfresco.util.EqualsHelper;
|
||||||
import org.apache.chemistry.opencmis.commons.PropertyIds;
|
|
||||||
import org.apache.chemistry.opencmis.commons.data.Properties;
|
|
||||||
import org.apache.chemistry.opencmis.commons.data.PropertyData;
|
import org.apache.chemistry.opencmis.commons.data.PropertyData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,39 +51,30 @@ public class Node implements Comparable<Node>
|
|||||||
{
|
{
|
||||||
protected NodeRef nodeRef;
|
protected NodeRef nodeRef;
|
||||||
protected String name;
|
protected String name;
|
||||||
|
|
||||||
|
// TODO needed for favourties - backwards compat' - we could also choose to split of NodeInfo / Node impl's etc
|
||||||
protected String title;
|
protected String title;
|
||||||
protected NodeRef guid; // TODO review - do we need for favorites (backwards compat') ?
|
protected NodeRef guid;
|
||||||
protected String description;
|
protected String description;
|
||||||
protected Date createdAt;
|
|
||||||
protected Date modifiedAt;
|
|
||||||
protected String createdBy;
|
protected String createdBy;
|
||||||
protected String modifiedBy;
|
protected String modifiedBy;
|
||||||
|
|
||||||
protected String primaryPath;
|
protected Date createdAt;
|
||||||
|
protected Date modifiedAt;
|
||||||
|
protected UserInfo createdByUser;
|
||||||
|
protected UserInfo modifiedByUser;
|
||||||
|
|
||||||
|
protected NodeRef parentNodeRef;
|
||||||
|
protected PathInfo pathInfo;
|
||||||
protected String prefixTypeQName;
|
protected String prefixTypeQName;
|
||||||
|
|
||||||
|
protected List<String> aspectNames;
|
||||||
|
|
||||||
protected Map<String, Serializable> props;
|
protected Map<String, Serializable> props;
|
||||||
|
|
||||||
private static final List<QName> EXCLUDED_PROPS = Arrays.asList(
|
|
||||||
ContentModel.PROP_NAME,
|
|
||||||
ContentModel.PROP_TITLE,
|
|
||||||
ContentModel.PROP_DESCRIPTION,
|
|
||||||
ContentModel.PROP_MODIFIER,
|
|
||||||
ContentModel.PROP_MODIFIED,
|
|
||||||
ContentModel.PROP_CREATOR,
|
|
||||||
ContentModel.PROP_CREATED,
|
|
||||||
ContentModel.PROP_CONTENT,
|
|
||||||
ContentModel.PROP_LOCALE,
|
|
||||||
ContentModel.PROP_NODE_UUID,
|
|
||||||
ContentModel.PROP_STORE_IDENTIFIER,
|
|
||||||
ContentModel.PROP_STORE_PROTOCOL,
|
|
||||||
ContentModel.PROP_NODE_DBID,
|
|
||||||
ContentModel.PROP_INITIAL_VERSION,
|
|
||||||
ContentModel.PROP_AUTO_VERSION_PROPS,
|
|
||||||
ContentModel.PROP_AUTO_VERSION);
|
|
||||||
|
|
||||||
// TODO fixme !
|
// TODO fixme !
|
||||||
public Node(NodeRef nodeRef, Map<QName, Serializable> nodeProps, NamespaceService namespaceService)
|
// 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<QName, Serializable> nodeProps, ServiceRegistry sr)
|
||||||
{
|
{
|
||||||
if(nodeRef == null)
|
if(nodeRef == null)
|
||||||
{
|
{
|
||||||
@@ -96,7 +82,9 @@ public class Node implements Comparable<Node>
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.nodeRef = nodeRef;
|
this.nodeRef = nodeRef;
|
||||||
mapProperties(nodeProps, namespaceService);
|
this.parentNodeRef = parentNodeRef;
|
||||||
|
|
||||||
|
mapBasicInfo(nodeProps, sr);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Object getValue(Map<String, PropertyData<?>> props, String name)
|
protected Object getValue(Map<String, PropertyData<?>> props, String name)
|
||||||
@@ -106,53 +94,42 @@ public class Node implements Comparable<Node>
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
public Node(NodeRef nodeRef, Properties properties)
|
|
||||||
{
|
|
||||||
this.nodeRef = nodeRef;
|
|
||||||
|
|
||||||
Map<String, PropertyData<?>> props = properties.getProperties();
|
|
||||||
|
|
||||||
this.guid = nodeRef;
|
|
||||||
|
|
||||||
this.name = (String)getValue(props, PropertyIds.NAME);
|
|
||||||
this.title = (String)getValue(props, ContentModel.PROP_TITLE.toString());
|
|
||||||
this.description = (String)getValue(props, PropertyIds.DESCRIPTION);
|
|
||||||
|
|
||||||
GregorianCalendar cal = (GregorianCalendar)getValue(props, PropertyIds.CREATION_DATE);
|
|
||||||
this.createdAt = cal.getTime();
|
|
||||||
cal = (GregorianCalendar)getValue(props, PropertyIds.LAST_MODIFICATION_DATE);
|
|
||||||
this.modifiedAt = cal.getTime();
|
|
||||||
this.createdBy = (String)getValue(props, PropertyIds.CREATED_BY);
|
|
||||||
this.modifiedBy = (String)getValue(props, PropertyIds.LAST_MODIFIED_BY);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
public Node()
|
public Node()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void mapProperties(Map<QName, Serializable> nodeProps, NamespaceService namespaceService)
|
protected void mapBasicInfo(Map<QName, Serializable> nodeProps, ServiceRegistry sr)
|
||||||
{
|
{
|
||||||
|
PersonService personService = sr.getPersonService();
|
||||||
|
|
||||||
// TODO review backwards compat' for favorites & others (eg. set guid explicitly where still needed)
|
// TODO review backwards compat' for favorites & others (eg. set guid explicitly where still needed)
|
||||||
//this.guid = nodeRef;
|
//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);
|
this.name = (String)nodeProps.get(ContentModel.PROP_NAME);
|
||||||
this.title = (String)nodeProps.get(ContentModel.PROP_TITLE);
|
|
||||||
this.description = (String)nodeProps.get(ContentModel.PROP_DESCRIPTION);
|
|
||||||
|
|
||||||
this.createdAt = (Date)nodeProps.get(ContentModel.PROP_CREATED);
|
this.createdAt = (Date)nodeProps.get(ContentModel.PROP_CREATED);
|
||||||
this.createdBy = (String)nodeProps.get(ContentModel.PROP_CREATOR);
|
this.createdByUser = lookupUserInfo((String)nodeProps.get(ContentModel.PROP_CREATOR), personService);
|
||||||
|
|
||||||
this.modifiedAt = (Date)nodeProps.get(ContentModel.PROP_MODIFIED);
|
this.modifiedAt = (Date)nodeProps.get(ContentModel.PROP_MODIFIED);
|
||||||
this.modifiedBy = (String)nodeProps.get(ContentModel.PROP_MODIFIER);
|
this.modifiedByUser = lookupUserInfo((String)nodeProps.get(ContentModel.PROP_MODIFIER), personService);
|
||||||
|
|
||||||
this.props = new HashMap<>(nodeProps.size());
|
|
||||||
|
|
||||||
for (Map.Entry<QName, Serializable> entry : nodeProps.entrySet()) {
|
|
||||||
QName propQName = entry.getKey();
|
|
||||||
if (! EXCLUDED_PROPS.contains(propQName)) {
|
|
||||||
props.put(entry.getKey().toPrefixString(namespaceService), entry.getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO refactor & optimise to avoid multiple person lookups
|
||||||
|
private UserInfo lookupUserInfo(final String userName, final PersonService personService) {
|
||||||
|
|
||||||
|
String sysUserName = AuthenticationUtil.getSystemUserName();
|
||||||
|
if (userName.equals(sysUserName) || (AuthenticationUtil.isMtEnabled() && userName.startsWith(sysUserName+"@")))
|
||||||
|
{
|
||||||
|
return new UserInfo(userName, userName, "");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PersonService.PersonInfo pInfo = personService.getPerson(personService.getPerson(userName));
|
||||||
|
return new UserInfo(userName, pInfo.getFirstName(), pInfo.getLastName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,8 +138,7 @@ public class Node implements Comparable<Node>
|
|||||||
this.guid = guid;
|
this.guid = guid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NodeRef getGuid()
|
public NodeRef getGuid() {
|
||||||
{
|
|
||||||
return guid;
|
return guid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,10 +155,6 @@ public class Node implements Comparable<Node>
|
|||||||
|
|
||||||
public void setNodeRef(NodeRef nodeRef)
|
public void setNodeRef(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
// if(nodeRef == null)
|
|
||||||
// {
|
|
||||||
// throw new IllegalArgumentException();
|
|
||||||
// }
|
|
||||||
this.nodeRef = nodeRef;
|
this.nodeRef = nodeRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,6 +178,14 @@ public class Node implements Comparable<Node>
|
|||||||
return modifiedBy;
|
return modifiedBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UserInfo getModifiedByUser() {
|
||||||
|
return modifiedByUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserInfo getCreatedByUser() {
|
||||||
|
return createdByUser;
|
||||||
|
}
|
||||||
|
|
||||||
public String getDescription()
|
public String getDescription()
|
||||||
{
|
{
|
||||||
return description;
|
return description;
|
||||||
@@ -231,22 +211,22 @@ public class Node implements Comparable<Node>
|
|||||||
this.createdBy = createdBy;
|
this.createdBy = createdBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPrimaryPath()
|
public PathInfo getPath()
|
||||||
{
|
{
|
||||||
return primaryPath;
|
return pathInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPrimaryPath(String primaryPath)
|
public void setPath(PathInfo pathInfo)
|
||||||
{
|
{
|
||||||
this.primaryPath = primaryPath;
|
this.pathInfo = pathInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getType()
|
public String getNodeType()
|
||||||
{
|
{
|
||||||
return prefixTypeQName;
|
return prefixTypeQName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setType(String prefixType)
|
public void setNodeType(String prefixType)
|
||||||
{
|
{
|
||||||
this.prefixTypeQName = prefixType;
|
this.prefixTypeQName = prefixType;
|
||||||
}
|
}
|
||||||
@@ -255,6 +235,23 @@ public class Node implements Comparable<Node>
|
|||||||
return this.props;
|
return this.props;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setProperties(Map props) {
|
||||||
|
this.props = props;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getAspectNames() {
|
||||||
|
return aspectNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAspectNames(List<String> aspectNames) {
|
||||||
|
this.aspectNames = aspectNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeRef getParentId()
|
||||||
|
{
|
||||||
|
return parentNodeRef;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean equals(Object other)
|
public boolean equals(Object other)
|
||||||
{
|
{
|
||||||
if(this == other)
|
if(this == other)
|
||||||
@@ -282,7 +279,7 @@ public class Node implements Comparable<Node>
|
|||||||
{
|
{
|
||||||
return "Node [nodeRef=" + nodeRef + ", type=" + prefixTypeQName + ", name=" + name + ", title="
|
return "Node [nodeRef=" + nodeRef + ", type=" + prefixTypeQName + ", name=" + name + ", title="
|
||||||
+ title + ", description=" + description + ", createdAt="
|
+ title + ", description=" + description + ", createdAt="
|
||||||
+ createdAt + ", modifiedAt=" + modifiedAt + ", createdBy=" + createdBy + ", modifiedBy="
|
+ createdAt + ", modifiedAt=" + modifiedAt + ", createdByUser=" + createdByUser + ", modifiedBy="
|
||||||
+ modifiedBy + ", primaryPath =" + primaryPath +"]";
|
+ modifiedByUser + ", pathInfo =" + pathInfo +"]";
|
||||||
}
|
}
|
||||||
}
|
}
|
64
source/java/org/alfresco/rest/api/model/PathInfo.java
Normal file
64
source/java/org/alfresco/rest/api/model/PathInfo.java
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package org.alfresco.rest.api.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of a path info
|
||||||
|
*
|
||||||
|
* @author janv
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class PathInfo
|
||||||
|
{
|
||||||
|
private String name;
|
||||||
|
private Boolean isComplete;
|
||||||
|
private List<ElementInfo> elements;
|
||||||
|
|
||||||
|
public PathInfo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public PathInfo(String name, Boolean isComplete, List<ElementInfo> elements)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.isComplete = isComplete;
|
||||||
|
this.elements = elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getIsComplete() {
|
||||||
|
return isComplete;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ElementInfo> getElements() {
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ElementInfo {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public ElementInfo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ElementInfo(String id, String name)
|
||||||
|
{
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
56
source/java/org/alfresco/rest/api/model/UserInfo.java
Normal file
56
source/java/org/alfresco/rest/api/model/UserInfo.java
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2015 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.rest.api.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of a user info
|
||||||
|
*
|
||||||
|
* @author janv
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class UserInfo
|
||||||
|
{
|
||||||
|
private String userName;
|
||||||
|
private String displayName;
|
||||||
|
|
||||||
|
public UserInfo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserInfo(String userName, String firstName, String lastName)
|
||||||
|
{
|
||||||
|
this.userName = userName;
|
||||||
|
this.displayName = ((firstName != null ? firstName + " " : "") + (lastName != null ? lastName : "")).replaceAll("^\\s+|\\s+$", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplayName() {
|
||||||
|
return displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserName() {
|
||||||
|
return userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "User [userName=" + userName + ", displayName=" + displayName + "]";
|
||||||
|
}
|
||||||
|
}
|
@@ -38,7 +38,7 @@ import java.util.List;
|
|||||||
* @author janv
|
* @author janv
|
||||||
*/
|
*/
|
||||||
@RelationshipResource(name = "children", entityResource = NodesEntityResource.class, title = "Folder children")
|
@RelationshipResource(name = "children", entityResource = NodesEntityResource.class, title = "Folder children")
|
||||||
public class NodeChildrenRelation implements RelationshipResourceAction.Read<Node>, RelationshipResourceAction.Create<Folder>, InitializingBean
|
public class NodeChildrenRelation implements RelationshipResourceAction.Read<Node>, RelationshipResourceAction.Create<Node>, InitializingBean
|
||||||
{
|
{
|
||||||
private Nodes nodes;
|
private Nodes nodes;
|
||||||
|
|
||||||
@@ -84,22 +84,22 @@ public class NodeChildrenRelation implements RelationshipResourceAction.Read<Nod
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create one or more sub-folders below parent folder. Note: can also use well-known alias, eg. -root- or -my-
|
* Create one or more nodes (folder or empty file) below parent folder.
|
||||||
*
|
*
|
||||||
* TODO also consider option to create path - eg. by passing name path in name (see Sparta API as an example) ... or should this be a separate API ?
|
* Note: for parent folder nodeId, can also use well-known alias, eg. -root- or -my-
|
||||||
*
|
*
|
||||||
* If parentFolderNodeId does not exist, EntityNotFoundException (status 404).
|
* If parentFolderNodeId does not exist, EntityNotFoundException (status 404).
|
||||||
* If parentFolderNodeId does not represent a folder, InvalidArgumentException (status 400).
|
* If parentFolderNodeId does not represent a folder, InvalidArgumentException (status 400).
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@WebApiDescription(title="Create one (or more) folder(s) as a child of folder identified by parentFolderNodeId")
|
@WebApiDescription(title="Create one (or more) nodes as children of folder identified by parentFolderNodeId")
|
||||||
public List<Folder> create(String parentFolderNodeId, List<Folder> folderInfos, Parameters parameters)
|
public List<Node> create(String parentFolderNodeId, List<Node> nodeInfos, Parameters parameters)
|
||||||
{
|
{
|
||||||
List<Folder> result = new ArrayList<>(folderInfos.size());
|
List<Node> result = new ArrayList<>(nodeInfos.size());
|
||||||
|
|
||||||
for (Folder folderInfo : folderInfos)
|
for (Node nodeInfo : nodeInfos)
|
||||||
{
|
{
|
||||||
result.add(nodes.createFolder(parentFolderNodeId, folderInfo, parameters));
|
result.add(nodes.createNode(parentFolderNodeId, nodeInfo, parameters));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@@ -27,23 +27,32 @@ package org.alfresco.rest.api.nodes;
|
|||||||
|
|
||||||
import org.alfresco.rest.api.Nodes;
|
import org.alfresco.rest.api.Nodes;
|
||||||
import org.alfresco.rest.api.model.Node;
|
import org.alfresco.rest.api.model.Node;
|
||||||
|
import org.alfresco.rest.framework.BinaryProperties;
|
||||||
import org.alfresco.rest.framework.WebApiDescription;
|
import org.alfresco.rest.framework.WebApiDescription;
|
||||||
import org.alfresco.rest.framework.WebApiParam;
|
import org.alfresco.rest.framework.WebApiParam;
|
||||||
|
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||||
import org.alfresco.rest.framework.resource.EntityResource;
|
import org.alfresco.rest.framework.resource.EntityResource;
|
||||||
|
import org.alfresco.rest.framework.resource.actions.interfaces.BinaryResourceAction;
|
||||||
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
|
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
|
||||||
|
import org.alfresco.rest.framework.resource.content.BasicContentInfo;
|
||||||
|
import org.alfresco.rest.framework.resource.content.BinaryResource;
|
||||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||||
import org.alfresco.util.ParameterCheck;
|
import org.alfresco.util.ParameterCheck;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of an Entity Resource for a Node
|
* An implementation of an Entity Resource for a Node (file or folder)
|
||||||
*
|
*
|
||||||
* @author sglover
|
* @author sglover
|
||||||
* @author Gethin James
|
* @author Gethin James
|
||||||
* @author janv
|
* @author janv
|
||||||
*/
|
*/
|
||||||
@EntityResource(name="nodes", title = "Nodes")
|
@EntityResource(name="nodes", title = "Nodes")
|
||||||
public class NodesEntityResource implements EntityResourceAction.ReadById<Node>, EntityResourceAction.Delete, EntityResourceAction.Update<Node>, InitializingBean
|
public class NodesEntityResource implements
|
||||||
|
EntityResourceAction.ReadById<Node>, EntityResourceAction.Delete, EntityResourceAction.Update<Node>,
|
||||||
|
BinaryResourceAction.Read, BinaryResourceAction.Update, InitializingBean
|
||||||
{
|
{
|
||||||
private Nodes nodes;
|
private Nodes nodes;
|
||||||
|
|
||||||
@@ -61,13 +70,10 @@ public class NodesEntityResource implements EntityResourceAction.ReadById<Node>,
|
|||||||
/**
|
/**
|
||||||
* Returns information regarding the node 'nodeId' - folder or document
|
* Returns information regarding the node 'nodeId' - folder or document
|
||||||
*
|
*
|
||||||
* TODO other metadata/properties & permissions etc ...
|
|
||||||
*
|
|
||||||
* @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-" or "-my-"
|
||||||
*
|
*
|
||||||
* Optional parameters:
|
* Optional parameters:
|
||||||
* - path
|
* - path
|
||||||
* - incPrimaryPath
|
|
||||||
*/
|
*/
|
||||||
@WebApiDescription(title = "Get Node Information", description = "Get information for the node with id 'nodeId'")
|
@WebApiDescription(title = "Get Node Information", description = "Get information for the node with id 'nodeId'")
|
||||||
@WebApiParam(name = "nodeId", title = "The node id")
|
@WebApiParam(name = "nodeId", title = "The node id")
|
||||||
@@ -76,15 +82,30 @@ public class NodesEntityResource implements EntityResourceAction.ReadById<Node>,
|
|||||||
return nodes.getFolderOrDocument(nodeId, parameters);
|
return nodes.getFolderOrDocument(nodeId, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@WebApiDescription(title = "Download content", description = "Download content")
|
||||||
|
@BinaryProperties({"content"})
|
||||||
|
public BinaryResource readProperty(String fileNodeId, Parameters parameters) throws EntityNotFoundException
|
||||||
|
{
|
||||||
|
return nodes.getContent(fileNodeId, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@WebApiDescription(title = "Upload content", description = "Upload content")
|
||||||
|
@BinaryProperties({"content"})
|
||||||
|
public void update(String fileNodeId, BasicContentInfo contentInfo, InputStream stream, Parameters parameters)
|
||||||
|
{
|
||||||
|
nodes.updateContent(fileNodeId, contentInfo, stream, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update info on the node 'nodeId' - folder or document
|
* Update info on the node 'nodeId' - folder or document
|
||||||
*
|
*
|
||||||
* Initially, name, title &/or description. Note: changing name is a "rename" (and must be unique within the current parent folder).
|
* Can update name (which is a "rename" and hence must be unique within the current parent folder)
|
||||||
*
|
* or update other properties.
|
||||||
* TODO other metadata/properties & permissions etc ...
|
|
||||||
*
|
*
|
||||||
* @param nodeId String nodeId of node (folder or document)
|
* @param nodeId String nodeId of node (folder or document)
|
||||||
* @param nodeInfo node entity with info to update (eg. name, title, description ...)
|
* @param nodeInfo node entity with info to update (eg. name, properties ...)
|
||||||
* @param parameters
|
* @param parameters
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@@ -31,6 +31,7 @@ import java.util.Locale;
|
|||||||
|
|
||||||
import org.alfresco.repo.content.MimetypeMap;
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
|
import org.alfresco.repo.web.scripts.BufferedRequest;
|
||||||
import org.alfresco.rest.framework.core.ResourceInspector;
|
import org.alfresco.rest.framework.core.ResourceInspector;
|
||||||
import org.alfresco.rest.framework.core.ResourceLocator;
|
import org.alfresco.rest.framework.core.ResourceLocator;
|
||||||
import org.alfresco.rest.framework.core.ResourceMetadata;
|
import org.alfresco.rest.framework.core.ResourceMetadata;
|
||||||
@@ -48,6 +49,7 @@ import org.apache.commons.lang.StringUtils;
|
|||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
|
import org.springframework.extensions.webscripts.WrappingWebScriptRequest;
|
||||||
import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest;
|
import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
@@ -152,6 +154,14 @@ public class ResourceWebScriptPut extends AbstractResourceWebScript implements P
|
|||||||
logger.warn("Failed to get the input stream.", error);
|
logger.warn("Failed to get the input stream.", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (req instanceof WrappingWebScriptRequest)
|
||||||
|
{
|
||||||
|
// TODO review REST fwk change
|
||||||
|
// eg. BufferredRequest
|
||||||
|
WrappingWebScriptRequest wrappedRequest = (WrappingWebScriptRequest) req;
|
||||||
|
return wrappedRequest.getContent().getInputStream();
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user