Merged searchapi (5.2.1) to 5.2.N (5.2.1)

129774 gjames: SEARCH-113: Moving more api logic to helper classes, using a "trait" style


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@130165 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Gethin James
2016-09-06 14:14:29 +00:00
parent ff2ce9d706
commit bfd32ef859
26 changed files with 1555 additions and 1303 deletions

View File

@@ -53,6 +53,7 @@ import org.alfresco.rest.framework.resource.content.FileBinaryResource;
import org.alfresco.rest.framework.resource.content.NodeBinaryResource;
import org.alfresco.rest.framework.resource.parameters.Params;
import org.alfresco.rest.framework.tools.ApiAssistant;
import org.alfresco.rest.framework.tools.ResponseWriter;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -80,7 +81,7 @@ import org.springframework.http.HttpMethod;
*/
// TODO for requests that pass in input streams e.g. binary content for workflow, this is going to need a way to re-read the input stream a la
// code in RepositoryContainer due to retrying transaction logic
public abstract class AbstractResourceWebScript extends ApiWebScript implements HttpMethodSupport, ActionExecutor
public abstract class AbstractResourceWebScript extends ApiWebScript implements HttpMethodSupport, ActionExecutor, ResponseWriter
{
private static Log logger = LogFactory.getLog(AbstractResourceWebScript.class);
@@ -146,18 +147,18 @@ public abstract class AbstractResourceWebScript extends ApiWebScript implements
}
else
{
renderJsonResponse(res, toSerialize);
renderJsonResponse(res, toSerialize, assistant.getJsonHelper());
}
}
}
catch (AlfrescoRuntimeException | ApiException | WebScriptException xception )
{
assistant.renderException(xception, res);
renderException(xception, res, assistant);
}
catch (RuntimeException runtimeException)
{
assistant.renderException(runtimeException, res);
renderException(runtimeException, res, assistant);
}
}
@@ -165,7 +166,7 @@ public abstract class AbstractResourceWebScript extends ApiWebScript implements
{
final String entityCollectionName = ResourceInspector.findEntityCollectionNameName(resource.getMetaData());
final ResourceOperation operation = resource.getMetaData().getOperation(getHttpMethod());
final WithResponse callBack = new WithResponse(operation.getSuccessStatus(), ApiAssistant.DEFAULT_JSON_CONTENT,ApiAssistant.CACHE_NEVER);
final WithResponse callBack = new WithResponse(operation.getSuccessStatus(), DEFAULT_JSON_CONTENT,CACHE_NEVER);
Object toReturn = transactionService.getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionHelper.RetryingTransactionCallback<Object>()
{
@@ -199,7 +200,7 @@ public abstract class AbstractResourceWebScript extends ApiWebScript implements
{
NodeBinaryResource nodeResource = (NodeBinaryResource) resource;
ContentInfo contentInfo = nodeResource.getContentInfo();
assistant.setContentInfoOnResponse(res, contentInfo);
setContentInfoOnResponse(res, contentInfo);
// if requested, set attachment
boolean attach = StringUtils.isNotEmpty(nodeResource.getAttachFileName());
Map<String, Object> model = getModelForCacheDirective(nodeResource.getCacheDirective());
@@ -217,70 +218,6 @@ public abstract class AbstractResourceWebScript extends ApiWebScript implements
return null;
}
/**
* The response status must be set before the response is written by Jackson (which will by default close and commit the response).
* In a r/w txn, web script buffered responses ensure that it doesn't really matter but for r/o txns this is important.
*
* If you set content information via the contentInfo object and ALSO the headers then "headers" will win because they are
* set last.
*
* @param res
* @param status
* @param cache
* @param contentInfo
* @param headers
*/
public void setResponse(final WebScriptResponse res, int status, Cache cache, ContentInfo contentInfo, Map<String, List<String>> headers)
{
res.setStatus(status);
if (cache != null) res.setCache(cache);
assistant.setContentInfoOnResponse(res,contentInfo);
if (headers != null && !headers.isEmpty())
{
for (Map.Entry<String, List<String>> header:headers.entrySet())
{
for (int i=0; i < header.getValue().size(); i++) {
if (i==0)
{
//If its the first one then set the header overwriting.
res.setHeader(header.getKey(), header.getValue().get(i));
}
else
{
//If its not the first one than update the header
res.addHeader(header.getKey(), header.getValue().get(i));
}
}
}
}
}
protected void setResponse(final WebScriptResponse res, WithResponse withResponse)
{
setResponse(res, withResponse.getStatus(), withResponse.getCache(), withResponse.getContentInfo(), withResponse.getHeaders());
}
/**
* Renders the result of an execution.
*
* @param res WebScriptResponse
* @param toSerialize result of an execution
* @throws IOException
*/
protected void renderJsonResponse(final WebScriptResponse res, final Object toSerialize)
throws IOException
{
assistant.getJsonHelper().withWriter(res.getOutputStream(), new JacksonHelper.Writer()
{
@Override
public void writeContents(JsonGenerator generator, ObjectMapper objectMapper)
throws JsonGenerationException, JsonMappingException, IOException
{
objectMapper.writeValue(generator, toSerialize);
}
});
}
public void setLocator(ResourceLocator locator)
{
this.locator = locator;

View File

@@ -38,6 +38,7 @@ import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResou
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceBinaryAction;
import org.alfresco.rest.framework.resource.parameters.Params;
import org.alfresco.rest.framework.tools.ApiAssistant;
import org.alfresco.rest.framework.tools.RecognizedParamsExtractor;
import org.apache.commons.lang.StringUtils;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptResponse;
@@ -48,7 +49,7 @@ import org.springframework.http.HttpMethod;
*
* @author Gethin James
*/
public class ResourceWebScriptDelete extends AbstractResourceWebScript implements ParamsExtractor
public class ResourceWebScriptDelete extends AbstractResourceWebScript implements ParamsExtractor, RecognizedParamsExtractor
{
public ResourceWebScriptDelete()
@@ -63,7 +64,7 @@ public class ResourceWebScriptDelete extends AbstractResourceWebScript implement
{
String entityId = req.getServiceMatch().getTemplateVars().get(ResourceLocator.ENTITY_ID);
String relationshipId = req.getServiceMatch().getTemplateVars().get(ResourceLocator.RELATIONSHIP_ID);
final Params.RecognizedParams params = ResourceWebScriptHelper.getRecognizedParams(req);
final Params.RecognizedParams params = getRecognizedParams(req);
switch (resourceMeta.getType())
{
@@ -215,7 +216,7 @@ public class ResourceWebScriptDelete extends AbstractResourceWebScript implement
public Void execute(final ResourceWithMetadata resource, final Params params, final WebScriptResponse res, boolean isReadOnly)
{
final ResourceOperation operation = resource.getMetaData().getOperation(HttpMethod.DELETE);
final WithResponse callBack = new WithResponse(operation.getSuccessStatus(), ApiAssistant.DEFAULT_JSON_CONTENT,ApiAssistant.CACHE_NEVER);
final WithResponse callBack = new WithResponse(operation.getSuccessStatus(), DEFAULT_JSON_CONTENT,CACHE_NEVER);
transactionService.getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionCallback<Void>()
{

View File

@@ -40,6 +40,7 @@ import org.alfresco.rest.framework.resource.content.BinaryResource;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Params;
import org.alfresco.rest.framework.resource.parameters.Params.RecognizedParams;
import org.alfresco.rest.framework.tools.RecognizedParamsExtractor;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -51,7 +52,7 @@ import org.springframework.http.HttpMethod;
*
* @author Gethin James
*/
public class ResourceWebScriptGet extends AbstractResourceWebScript implements ParamsExtractor
public class ResourceWebScriptGet extends AbstractResourceWebScript implements ParamsExtractor, RecognizedParamsExtractor
{
private static Log logger = LogFactory.getLog(ResourceWebScriptGet.class);
@@ -67,7 +68,7 @@ public class ResourceWebScriptGet extends AbstractResourceWebScript implements P
{
final String entityId = req.getServiceMatch().getTemplateVars().get(ResourceLocator.ENTITY_ID);
final String relationshipId = req.getServiceMatch().getTemplateVars().get(ResourceLocator.RELATIONSHIP_ID);
final RecognizedParams params = ResourceWebScriptHelper.getRecognizedParams(req);
final RecognizedParams params = getRecognizedParams(req);
switch (resourceMeta.getType())
{

View File

@@ -67,6 +67,7 @@ import org.alfresco.rest.framework.resource.parameters.where.Query;
import org.alfresco.rest.framework.resource.parameters.where.QueryImpl;
import org.alfresco.rest.framework.resource.parameters.where.WhereCompiler;
import org.alfresco.rest.framework.tools.ApiAssistant;
import org.alfresco.rest.framework.tools.ResponseWriter;
import org.alfresco.util.Pair;
import org.alfresco.util.PropertyCheck;
import org.antlr.runtime.RecognitionException;
@@ -92,336 +93,10 @@ import org.springframework.http.HttpMethod;
public class ResourceWebScriptHelper
{
private static Log logger = LogFactory.getLog(ResourceWebScriptHelper.class);
public static final String PARAM_RELATIONS = "relations";
public static final String PARAM_FILTER_FIELDS = "fields";
@Deprecated
public static final String PARAM_FILTER_PROPERTIES = "properties";
public static final String PARAM_PAGING_SKIP = "skipCount";
public static final String PARAM_PAGING_MAX = "maxItems";
public static final String PARAM_ORDERBY = "orderBy";
public static final String PARAM_WHERE = "where";
public static final String PARAM_SELECT = "select";
public static final String PARAM_INCLUDE = "include";
public static final String PARAM_INCLUDE_SOURCE_ENTITY = "includeSource";
public static final List<String> KNOWN_PARAMS = Arrays.asList(
PARAM_RELATIONS, PARAM_FILTER_PROPERTIES, PARAM_FILTER_FIELDS,PARAM_PAGING_SKIP,PARAM_PAGING_MAX,
PARAM_ORDERBY, PARAM_WHERE, PARAM_SELECT, PARAM_INCLUDE_SOURCE_ENTITY);
private ResourceLocator locator;
private ActionExecutor executor;
/**
* Takes the web request and looks for a "fields" parameter (otherwise deprecated "properties" parameter).
*
* Parses the parameter and produces a list of bean properties to use as a filter A
* SimpleBeanPropertyFilter it returned that uses the bean properties. If no
* filter param is set then a default BeanFilter is returned that will never
* filter fields (ie. Returns all bean properties).
*
* @param filterParams String
* @return BeanPropertyFilter - if no parameter then returns a new
* ReturnAllBeanProperties class
*/
public static BeanPropertiesFilter getFilter(String filterParams)
{
return getFilter(filterParams, null);
}
/**
* Takes the web request and looks for a "fields" parameter (otherwise deprecated "properties" parameter).
*
* Parses the parameter and produces a list of bean properties to use as a filter A
* SimpleBeanPropertyFilter it returned that uses the bean properties. If no
* filter param is set then a default BeanFilter is returned that will never
* filter fields (ie. Returns all bean properties).
*
* If selectList is provided then it will take precedence (ie. be included) over the fields/properties filter
* for top-level entries (bean properties).
*
* For example, this will return entries from both select & properties, eg.
*
* select=abc,def&properties=id,name,ghi
*
* Note: it should be noted that API-generic "fields" clause does not currently work for sub-entries.
*
* Hence, even if the API-specific "select" clause allows selection of a sub-entries this cannot be used
* with "fields" filtering. For example, an API-specific method may implement and return "abc/blah", eg.
*
* select=abc/blah
*
* However the following will not return "abc/blah" if used with fields filtering, eg.
*
* select=abc/blah&fields=id,name,ghi
*
* If fields filtering is desired then it would require "abc" to be selected and returned as a whole, eg.
*
* select=abc&fields=id,name,ghi
*
* @param filterParams
* @param selectList
* @return
*/
public static BeanPropertiesFilter getFilter(String filterParams, List<String> selectList)
{
if (filterParams != null)
{
StringTokenizer st = new StringTokenizer(filterParams, ",");
Set<String> filteredProperties = new HashSet<String>(st.countTokens());
while (st.hasMoreTokens())
{
filteredProperties.add(st.nextToken());
}
// if supplied, the select takes precedence over the filter (fields/properties) for top-level bean properties
if (selectList != null)
{
for (String select : selectList)
{
String[] split = select.split("/");
filteredProperties.add(split[0]);
}
}
logger.debug("Filtering using the following properties: " + filteredProperties);
BeanPropertiesFilter filter = new BeanPropertiesFilter(filteredProperties);
return filter;
}
return BeanPropertiesFilter.ALLOW_ALL;
}
/**
* Takes the web request and looks for a "relations" parameter Parses the
* parameter and produces a list of bean properties to use as a filter A
* SimpleBeanPropertiesFilter it returned that uses the properties If no
* filter param is set then a default BeanFilter is returned that will never
* filter properties (ie. Returns all bean properties).
*
* @param filterParams String
* @return BeanPropertiesFilter - if no parameter then returns a new
* ReturnAllBeanProperties class
*/
public static Map<String, BeanPropertiesFilter> getRelationFilter(String filterParams)
{
if (filterParams != null)
{
// Split by a comma when not in a bracket
String[] relations = filterParams.split(",(?![^()]*+\\))");
Map<String, BeanPropertiesFilter> filterMap = new HashMap<String, BeanPropertiesFilter>(relations.length);
for (String relation : relations)
{
int bracketLocation = relation.indexOf("(");
if (bracketLocation != -1)
{
// We have properties
String relationKey = relation.substring(0, bracketLocation);
String props = relation.substring(bracketLocation + 1, relation.length() - 1);
filterMap.put(relationKey, getFilter(props));
}
else
{
// no properties so just get the String
filterMap.put(relation, getFilter(null));
}
}
return filterMap;
}
return Collections.emptyMap();
}
/**
* Takes the "select" parameter and turns it into a List<String> property names
* @param selectParam String
* @return bean property names potentially using JSON Pointer syntax
*/
@SuppressWarnings("unchecked")
@Deprecated
public static List<String> getSelectClause(String selectParam) throws InvalidArgumentException
{
return getClause(selectParam, "SELECT");
}
/**
* Takes the "include" parameter and turns it into a List<String> property names
* @param includeParam String
* @return bean property names potentially using JSON Pointer syntax
*/
@SuppressWarnings("unchecked")
public static List<String> getIncludeClause(String includeParam) throws InvalidArgumentException
{
return getClause(includeParam, "INCLUDE");
}
private static List<String> getClause(String param, String paramName)
{
if (param == null) return Collections.emptyList();
try {
CommonTree selectedPropsTree = WhereCompiler.compileSelectClause(param);
if (selectedPropsTree instanceof CommonErrorNode)
{
logger.debug("Error parsing the "+paramName+" clause "+selectedPropsTree);
throw new InvalidSelectException(paramName, selectedPropsTree);
}
if (selectedPropsTree.getChildCount() == 0 && !selectedPropsTree.getText().isEmpty())
{
return Arrays.asList(selectedPropsTree.getText());
}
List<Tree> children = (List<Tree>) selectedPropsTree.getChildren();
if (children!= null && !children.isEmpty())
{
List<String> properties = new ArrayList<String>(children.size());
for (Tree child : children) {
properties.add(child.getText());
}
return properties;
}
}
catch (RewriteCardinalityException re)
{
//Catch any error so it doesn't get thrown up the stack
logger.debug("Unhandled Error parsing the "+paramName+" clause: "+re);
}
catch (RecognitionException e)
{
logger.debug("Error parsing the \"+paramName+\" clause: "+param);
}
catch (InvalidQueryException iqe)
{
throw new InvalidSelectException(paramName, iqe.getQueryParam());
}
//Default to throw out an invalid query
throw new InvalidSelectException(paramName, param);
}
/**
* Takes the "where" parameter and turns it into a Java Object that can be used for querying
* @param whereParam String
* @return Query a parsed version of the where clause, represented in Java
*/
public static Query getWhereClause(String whereParam) throws InvalidQueryException
{
if (whereParam == null) return QueryImpl.EMPTY;
try {
CommonTree whereTree = WhereCompiler.compileWhereClause(whereParam);
if (whereTree instanceof CommonErrorNode)
{
logger.debug("Error parsing the WHERE clause "+whereTree);
throw new InvalidQueryException(whereTree);
}
return new QueryImpl(whereTree);
} catch (RewriteCardinalityException re) { //Catch any error so it doesn't get thrown up the stack
logger.info("Unhandled Error parsing the WHERE clause: "+re);
} catch (RecognitionException e) {
whereParam += ", "+WhereCompiler.resolveMessage(e);
logger.info("Error parsing the WHERE clause: "+whereParam);
}
//Default to throw out an invalid query
throw new InvalidQueryException(whereParam);
}
/**
* Takes the Sort parameter as a String and parses it into a List of SortColumn objects.
* The format is a comma seperated list of "columnName sortDirection",
* e.g. "name DESC, age ASC". It is not case sensitive and the sort direction is optional
* It default to sort ASCENDING.
* @param sortParams - String passed in on the request
* @return - the sort columns or an empty list if the params were invalid.
*/
public static List<SortColumn> getSort(String sortParams)
{
if (sortParams != null)
{
StringTokenizer st = new StringTokenizer(sortParams, ",");
List<SortColumn> sortedColumns = new ArrayList<SortColumn>(st.countTokens());
while (st.hasMoreTokens())
{
String token = st.nextToken();
StringTokenizer columnDesc = new StringTokenizer(token, " ");
if (columnDesc.countTokens() <= 2)
{
String columnName = columnDesc.nextToken();
String sortOrder = SortColumn.ASCENDING;
if (columnDesc.hasMoreTokens())
{
String sortDef = columnDesc.nextToken().toUpperCase();
if (SortColumn.ASCENDING.equals(sortDef) || SortColumn.DESCENDING.equals(sortDef))
{
sortOrder = sortDef;
}
else
{
logger.debug("Invalid sort order definition ("+sortDef+"). Valid values are "+SortColumn.ASCENDING+" or "+SortColumn.DESCENDING+".");
}
}
sortedColumns.add(new SortColumn(columnName, SortColumn.ASCENDING.equals(sortOrder)));
}
// filteredProperties.add();
}
// logger.debug("Filtering using the following properties: " + filteredProperties);
// BeanPropertiesFilter filter = new BeanPropertiesFilter(filteredProperties);
return sortedColumns;
}
return Collections.emptyList();
}
/**
* Extracts the body contents from the request
*
* @param req the request
* @param jsonHelper Jackson Helper
* @param requiredType the type to return
* @return the Object in the required type
*/
public static <T> T extractJsonContent(WebScriptRequest req, JacksonHelper jsonHelper, Class<T> requiredType)
{
Reader reader;
try
{
reader = req.getContent().getReader();
return jsonHelper.construct(reader, requiredType);
}
catch (JsonMappingException e)
{
logger.warn("Could not read content from HTTP request body.", e);
throw new InvalidArgumentException("Could not read content from HTTP request body.");
}
catch (IOException e)
{
throw new ApiException("Could not read content from HTTP request body.", e.getCause());
}
}
/**
* Extracts the body contents from the request as a List, the JSON can be an array or just a single value without the [] symbols
*
* @param req the request
* @param jsonHelper Jackson Helper
* @param requiredType the type to return (without the List param)
* @return A List of "Object" as the required type
*/
public static <T> List<T> extractJsonContentAsList(WebScriptRequest req, JacksonHelper jsonHelper, Class<T> requiredType)
{
Reader reader;
try
{
reader = req.getContent().getReader();
return jsonHelper.constructList(reader, requiredType);
}
catch (IOException e)
{
throw new ApiException("Could not read content from HTTP request body.", e.getCause());
}
}
/**
* Set the id of theObj to the uniqueId. Attempts to find a set method and
* invoke it. If it fails it just swallows the exceptions and doesn't throw
@@ -471,41 +146,6 @@ public class ResourceWebScriptHelper
}
}
// /**
// * Renders the response result
// *
// * @param response
// * @param result
// */
// public static void renderResponseDep(Map<String, Object> response, Object result)
// {
//
// if (result == null) { return; }
//
// if (result instanceof Collection)
// {
// response.put("list", result);
// }
// else if (result instanceof CollectionWithPagingInfo)
// {
// CollectionWithPagingInfo<?> col = (CollectionWithPagingInfo<?>) result;
// if (col.getCollection() !=null && !col.getCollection().isEmpty())
// {
// response.put("list", col);
// }
// }
// else if (result instanceof Pair<?,?>)
// {
// Pair<?,?> aPair = (Pair<?, ?>) result;
// response.put("entry", aPair.getFirst());
// response.put("relations", aPair.getSecond());
// }
// else
// {
// response.put("entry", result);
// }
// }
/**
* Looks at the object passed in and recursively expands any @EmbeddedEntityResource annotations or related relationship.
* {@link org.alfresco.rest.framework.resource.EmbeddedEntityResource EmbeddedEntityResource} is expanded by calling the ReadById method for this entity.
@@ -677,7 +317,7 @@ public class ResourceWebScriptHelper
paramFilter = filters.get(resourceKey);
}
final Params executionParams = Params.valueOf(paramFilter, uniqueEntityId, params.getRequest());
final WithResponse callBack = new WithResponse(Status.STATUS_OK, ApiAssistant.DEFAULT_JSON_CONTENT,ApiAssistant.CACHE_NEVER);
final WithResponse callBack = new WithResponse(Status.STATUS_OK, ResponseWriter.DEFAULT_JSON_CONTENT,ResponseWriter.CACHE_NEVER);
//Read only because this only occurs for GET requests
Object result = executor.executeAction(resource, executionParams, callBack);
return processAdditionsToTheResponse(null, api, null, executionParams, result);
@@ -705,118 +345,6 @@ public class ResourceWebScriptHelper
return null; //default
}
/**
* Finds all request parameters that aren't already known about (eg. not paging or filter params)
* and returns them for use.
*
* @param req - the WebScriptRequest object
* @return the request parameters
*/
public static Map<String, String[]> getRequestParameters(WebScriptRequest req)
{
if (req!= null)
{
String[] paramNames = req.getParameterNames();
if (paramNames!= null)
{
Map<String, String[]> requestParameteters = new HashMap<String, String[]>(paramNames.length);
for (int i = 0; i < paramNames.length; i++)
{
String paramName = paramNames[i];
if (!KNOWN_PARAMS.contains(paramName))
{
String[] vals = req.getParameterValues(paramName);
requestParameteters.put(paramName, vals);
}
}
return requestParameteters;
}
}
return Collections.emptyMap();
}
/**
* Finds the formal set of params that any rest service could potentially have passed in as request params
* @param req WebScriptRequest
* @return RecognizedParams a POJO containing the params for use with the Params objects
*/
public static RecognizedParams getRecognizedParams(WebScriptRequest req)
{
Paging paging = findPaging(req);
List<SortColumn> sorting = getSort(req.getParameter(ResourceWebScriptHelper.PARAM_ORDERBY));
Map<String, BeanPropertiesFilter> relationFilter = getRelationFilter(req.getParameter(ResourceWebScriptHelper.PARAM_RELATIONS));
Query whereQuery = getWhereClause(req.getParameter(ResourceWebScriptHelper.PARAM_WHERE));
Map<String, String[]> requestParams = getRequestParameters(req);
boolean includeSource = Boolean.valueOf(req.getParameter(ResourceWebScriptHelper.PARAM_INCLUDE_SOURCE_ENTITY));
List<String> includedFields = getIncludeClause(req.getParameter(ResourceWebScriptHelper.PARAM_INCLUDE));
List<String> selectFields = getSelectClause(req.getParameter(ResourceWebScriptHelper.PARAM_SELECT));
String fields = req.getParameter(ResourceWebScriptHelper.PARAM_FILTER_FIELDS);
String properties = req.getParameter(ResourceWebScriptHelper.PARAM_FILTER_PROPERTIES);
if ((fields != null) && (properties != null))
{
if (logger.isWarnEnabled())
{
logger.warn("Taking 'fields' param [" + fields + "] and ignoring deprecated 'properties' param [" + properties + "]");
}
}
BeanPropertiesFilter filter = getFilter((fields != null ? fields : properties), includedFields);
return new RecognizedParams(requestParams, paging, filter, relationFilter, includedFields, selectFields, whereQuery, sorting, includeSource);
}
/**
* Find paging setings based on the request parameters.
*
* @param req
* @return Paging
*/
public static Paging findPaging(WebScriptRequest req)
{
int skipped = Paging.DEFAULT_SKIP_COUNT;
int max = Paging.DEFAULT_MAX_ITEMS;
String skip = req.getParameter(PARAM_PAGING_SKIP);
String maxItems = req.getParameter(PARAM_PAGING_MAX);
try
{
if (skip != null) { skipped = Integer.parseInt(skip);}
if (maxItems != null) { max = Integer.parseInt(maxItems); }
if (skipped < 0)
{
throw new InvalidArgumentException("Negative values not supported for skipCount.");
}
if (max < 1)
{
throw new InvalidArgumentException("Only positive values supported for maxItems.");
}
}
catch (NumberFormatException error)
{
String errorMsg = "Invalid paging parameters skipCount: " + skip + ", maxItems:" + maxItems;
if (logger.isDebugEnabled())
{
logger.debug(errorMsg);
}
if (skip == null)
{
errorMsg = "Invalid paging parameter maxItems:" + maxItems;
}
if (maxItems == null)
{
errorMsg = "Invalid paging parameter skipCount:" + skip;
}
throw new InvalidArgumentException(errorMsg);
}
return Paging.valueOf(skipped, max);
}
public void setLocator(ResourceLocator locator)
{
this.locator = locator;

View File

@@ -45,6 +45,8 @@ import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResou
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Params;
import org.alfresco.rest.framework.resource.parameters.Params.RecognizedParams;
import org.alfresco.rest.framework.tools.RecognizedParamsExtractor;
import org.alfresco.rest.framework.tools.RequestReader;
import org.apache.commons.lang.StringUtils;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptRequestImpl;
@@ -56,7 +58,8 @@ import org.springframework.http.HttpMethod;
*
* @author Gethin James
*/
public class ResourceWebScriptPost extends AbstractResourceWebScript implements ParamsExtractor
public class ResourceWebScriptPost extends AbstractResourceWebScript implements ParamsExtractor,
RecognizedParamsExtractor, RequestReader
{
public ResourceWebScriptPost()
@@ -69,7 +72,7 @@ public class ResourceWebScriptPost extends AbstractResourceWebScript implements
@Override
public Params extractParams(ResourceMetadata resourceMeta, WebScriptRequest req)
{
final RecognizedParams params = ResourceWebScriptHelper.getRecognizedParams(req);
final RecognizedParams params = getRecognizedParams(req);
final String entityId = req.getServiceMatch().getTemplateVars().get(ResourceLocator.ENTITY_ID);
final String relationshipId = req.getServiceMatch().getTemplateVars().get(ResourceLocator.RELATIONSHIP_ID);
final ResourceOperation operation = resourceMeta.getOperation(HttpMethod.POST);
@@ -168,7 +171,7 @@ public class ResourceWebScriptPost extends AbstractResourceWebScript implements
Object jsonContent = null;
if (objType != null)
{
jsonContent = ResourceWebScriptHelper.extractJsonContent(req, assistant.getJsonHelper(), objType);
jsonContent = extractJsonContent(req, assistant.getJsonHelper(), objType);
}
if (isTypeOperation)
@@ -203,11 +206,11 @@ public class ResourceWebScriptPost extends AbstractResourceWebScript implements
if (isTypeOperation)
{
// Operations don't support a List as json body
return ResourceWebScriptHelper.extractJsonContent(req, assistant.getJsonHelper(), objType);
return extractJsonContent(req, assistant.getJsonHelper(), objType);
}
else
{
return ResourceWebScriptHelper.extractJsonContentAsList(req, assistant.getJsonHelper(), objType);
return extractJsonContentAsList(req, assistant.getJsonHelper(), objType);
}
}

View File

@@ -44,6 +44,8 @@ import org.alfresco.rest.framework.resource.content.BasicContentInfo;
import org.alfresco.rest.framework.resource.content.ContentInfoImpl;
import org.alfresco.rest.framework.resource.parameters.Params;
import org.alfresco.rest.framework.resource.parameters.Params.RecognizedParams;
import org.alfresco.rest.framework.tools.RecognizedParamsExtractor;
import org.alfresco.rest.framework.tools.RequestReader;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -57,7 +59,8 @@ import org.springframework.http.MediaType;
*
* @author Gethin James
*/
public class ResourceWebScriptPut extends AbstractResourceWebScript implements ParamsExtractor
public class ResourceWebScriptPut extends AbstractResourceWebScript implements ParamsExtractor,
RecognizedParamsExtractor, RequestReader
{
private static Log logger = LogFactory.getLog(ResourceWebScriptPut.class);
@@ -75,7 +78,7 @@ public class ResourceWebScriptPut extends AbstractResourceWebScript implements P
final String relationshipId = req.getServiceMatch().getTemplateVars().get(ResourceLocator.RELATIONSHIP_ID);
final String entityId = req.getServiceMatch().getTemplateVars().get(ResourceLocator.ENTITY_ID);
final RecognizedParams params = ResourceWebScriptHelper.getRecognizedParams(req);
final RecognizedParams params = getRecognizedParams(req);
final ResourceOperation operation = resourceMeta.getOperation(HttpMethod.PUT);
switch (resourceMeta.getType())
@@ -87,7 +90,7 @@ public class ResourceWebScriptPut extends AbstractResourceWebScript implements P
} else
{
Object putEnt = ResourceWebScriptHelper.extractJsonContent(req, assistant.getJsonHelper(), resourceMeta.getObjectType(operation));
Object putEnt = extractJsonContent(req, assistant.getJsonHelper(), resourceMeta.getObjectType(operation));
return Params.valueOf(entityId,params,putEnt, req);
}
case RELATIONSHIP:
@@ -96,7 +99,7 @@ public class ResourceWebScriptPut extends AbstractResourceWebScript implements P
throw new UnsupportedResourceOperationException("PUT is executed against the instance URL");
} else
{
Object putRel = ResourceWebScriptHelper.extractJsonContent(req, assistant.getJsonHelper(), resourceMeta.getObjectType(operation));
Object putRel = extractJsonContent(req, assistant.getJsonHelper(), resourceMeta.getObjectType(operation));
ResourceWebScriptHelper.setUniqueId(putRel,relationshipId);
return Params.valueOf(entityId, params, putRel, req);
}