RM-4952 Merge master into RM-4952_ReadOnlyParams.

This commit is contained in:
Tom Page
2017-04-20 15:06:05 +01:00
7 changed files with 1787 additions and 0 deletions

View File

@@ -127,6 +127,87 @@
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>apply-rm-community</id>
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>fetch-amps</id>
<phase>process-test-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-rm-community-share</artifactId>
<version>${project.version}</version>
<type>amp</type>
</artifactItem>
<artifactItem>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-rm-community-repo</artifactId>
<version>${project.version}</version>
<type>amp</type>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/amps</outputDirectory>
<useBaseVersion>true</useBaseVersion>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.alfresco.maven.plugin</groupId>
<artifactId>alfresco-maven-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<id>install-community-repo-amp</id>
<goals>
<goal>install</goal>
</goals>
<phase>process-test-resources</phase>
<configuration>
<backup>true</backup>
<ampLocation>
${project.build.directory}/amps/alfresco-rm-community-repo-${project.version}.amp
</ampLocation>
<warLocation>${project.build.directory}/alf-installation/tomcat/webapps/alfresco.war
</warLocation>
</configuration>
</execution>
<execution>
<id>install-community-share-amp</id>
<goals>
<goal>install</goal>
</goals>
<phase>process-test-resources</phase>
<configuration>
<backup>true</backup>
<ampLocation>
${project.build.directory}/amps/alfresco-rm-community-share-${project.version}.amp
</ampLocation>
<warLocation>${project.build.directory}/alf-installation/tomcat/webapps/share.war
</warLocation>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>apply-rm-enterprise</id>
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>

View File

@@ -0,0 +1,616 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2017 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.core.v0;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.dataprep.AlfrescoHttpClient;
import org.alfresco.dataprep.AlfrescoHttpClientFactory;
import org.alfresco.dataprep.ContentService;
import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
/**
* The base API class containing common methods for making v0 API requests
*
* @author Kristijan Conkas
* @since 2.5
*/
public abstract class BaseAPI
{
// logger
private static final Logger LOGGER = LoggerFactory.getLogger(BaseAPI.class);
/** exception key in JSON response body */
private static final String EXCEPTION_KEY = "exception";
protected static final String FILE_PLAN_PATH = "Sites/rm/documentLibrary";
protected static final String NODE_REF_WORKSPACE_SPACES_STORE = "workspace://SpacesStore/";
protected static final String NODE_PREFIX = "workspace/SpacesStore/";
protected static final String UPDATE_METADATA_API = "{0}node/{1}/formprocessor";
protected static final String ACTIONS_API = "{0}actionQueue";
protected static final String RM_ACTIONS_API = "{0}rma/actions/ExecutionQueue";
protected static final String RM_SITE_ID = "rm";
@Autowired
private AlfrescoHttpClientFactory alfrescoHttpClientFactory;
@Autowired
private ContentService contentService;
/**
* Helper method to extract list of properties values from result.
*
* @param result the response
* @return list of specified property values in result
* @throws RuntimeException for malformed response
*/
protected List<String> getPropertyValues(JSONObject result, String propertyName)
{
ArrayList<String> results = new ArrayList<String>();
try
{
JSONArray items = result.getJSONArray("items");
for (int i = 0; i < items.length(); i++)
{
results.add(items.getJSONObject(i).getString(propertyName));
}
}
catch (JSONException error)
{
throw new RuntimeException("Unable to parse result", error);
}
return results;
}
/**
* Helper method to extract property values from request result and put them in map as a list that corresponds to a unique property value.
*
* @param requestResult the request response
* @return a map containing information about multiple properties values that correspond to a unique one
* @throws RuntimeException for malformed response
*/
protected Map<String, List<String>> getPropertyValuesByUniquePropertyValue(JSONObject requestResult, String uniqueProperty, List<String> otherProperties)
{
Map<String, List<String>> valuesByUniqueProperty = new HashMap<>();
try
{
JSONArray items = requestResult.getJSONArray("items");
for (int i = 0; i < items.length(); i++)
{
List<String> otherPropertiesValues = new ArrayList<>();
for (int j = 0; j < otherProperties.size(); j++)
{
otherPropertiesValues.add(items.getJSONObject(i).get(otherProperties.get(j)).toString());
}
valuesByUniqueProperty.put(items.getJSONObject(i).getString(uniqueProperty), otherPropertiesValues);
}
}
catch (JSONException error)
{
throw new RuntimeException("Unable to parse result", error);
}
return valuesByUniqueProperty;
}
/**
* Retrieves the nodeRef of an item (category, folder or record) with the given path
*
* @param username the username
* @param password the password
* @param path the path to the container eg. in case of a category it would be the category name,
* in case of a folder it would be /categoryName/folderName
* when trying to get File Plan, the path would be ""
* @return the container nodeRef
*/
public String getItemNodeRef(String username, String password, String path)
{
return contentService.getNodeRefByPath(username, password, FILE_PLAN_PATH + path);
}
/**
* Retrieve a Cmis object by its path
*
* @param username the user's username
* @param password its password
* @param path the object path
* @return the object in case it exists, null if its does not exist
*/
protected CmisObject getObjectByPath(String username, String password, String path)
{
CmisObject object;
try
{
object = contentService.getCMISSession(username, password).getObjectByPath(path);
} catch (CmisObjectNotFoundException notFoundError)
{
return null;
}
return object;
}
/**
* Generic faceted request.
*
* @param username the username
* @param password the password
* @param parameters if the request has parameters
* @return result object (see API reference for more details), null for any errors
*/
protected JSONObject facetedRequest(String username, String password, List<NameValuePair> parameters, String requestURI)
{
String requestURL;
AlfrescoHttpClient client = alfrescoHttpClientFactory.getObject();
if (parameters == null || parameters.isEmpty())
{
requestURL = MessageFormat.format(
requestURI,
client.getAlfrescoUrl());
}
else
{
requestURL = MessageFormat.format(
requestURI,
client.getAlfrescoUrl(),
URLEncodedUtils.format(parameters, "UTF-8"));
}
client.close();
return doGetRequest(username, password, requestURL);
}
/**
* Helper method for GET requests
* @param adminUser user with administrative privileges
* @param adminPassword password for adminUser
* @param urlTemplate request URL template
* @param urlTemplateParams zero or more parameters used with <i>urlTemplate</i>
*/
protected JSONObject doGetRequest(String adminUser,
String adminPassword,
String urlTemplate,
String ... urlTemplateParams)
{
AlfrescoHttpClient client = alfrescoHttpClientFactory.getObject();
String requestUrl = MessageFormat.format(
urlTemplate,
client.getApiUrl(),
urlTemplateParams);
client.close();
try
{
return doRequest(HttpGet.class, requestUrl, adminUser, adminPassword, null);
}
catch (InstantiationException | IllegalAccessException error)
{
throw new IllegalArgumentException("doGetRequest failed", error);
}
}
/**
* Helper method for Delete requests
* @param adminUser user with administrative privileges
* @param adminPassword password for adminUser
* @param urlTemplate request URL template
* @param urlTemplateParams zero or more parameters used with <i>urlTemplate</i>
*/
protected JSONObject doDeleteRequest(String adminUser,
String adminPassword,
String urlTemplate,
String ... urlTemplateParams)
{
AlfrescoHttpClient client = alfrescoHttpClientFactory.getObject();
String requestUrl = MessageFormat.format(
urlTemplate,
client.getApiUrl(),
urlTemplateParams);
client.close();
try
{
return doRequest(HttpDelete.class, requestUrl, adminUser, adminPassword, null);
}
catch (InstantiationException | IllegalAccessException error)
{
throw new IllegalArgumentException("doDeleteRequest failed", error);
}
}
/**
* Helper method for PUT requests
* @param adminUser user with administrative privileges
* @param adminPassword password for adminUser
* @param requestParams zero or more endpoint specific request parameters
* @param urlTemplate request URL template
* @param urlTemplateParams zero or more parameters used with <i>urlTemplate</i>
*/
protected JSONObject doPutRequest(String adminUser,
String adminPassword,
JSONObject requestParams,
String urlTemplate,
String ... urlTemplateParams)
{
AlfrescoHttpClient client = alfrescoHttpClientFactory.getObject();
String requestUrl = MessageFormat.format(
urlTemplate,
client.getApiUrl(),
urlTemplateParams);
client.close();
try
{
return doRequest(HttpPut.class, requestUrl, adminUser, adminPassword, requestParams);
}
catch (InstantiationException | IllegalAccessException error)
{
throw new IllegalArgumentException("doPutRequest failed", error);
}
}
/**
* Helper method for POST requests
* @param adminUser user with administrative privileges
* @param adminPassword password for adminUser
* @param requestParams zero or more endpoint specific request parameters
* @param urlTemplate request URL template
* @param urlTemplateParams zero or more parameters used with <i>urlTemplate</i>
*/
protected JSONObject doPostRequest(String adminUser,
String adminPassword,
JSONObject requestParams,
String urlTemplate,
String ... urlTemplateParams)
{
AlfrescoHttpClient client = alfrescoHttpClientFactory.getObject();
String requestUrl = MessageFormat.format(
urlTemplate,
client.getApiUrl(),
urlTemplateParams);
client.close();
try
{
return doRequest(HttpPost.class, requestUrl, adminUser, adminPassword, requestParams);
}
catch (InstantiationException | IllegalAccessException error)
{
throw new IllegalArgumentException("doPostRequest failed", error);
}
}
/**
* Helper method for POST requests
*
* @param adminUser user with administrative privileges
* @param adminPassword password for adminUser
* @param requestParams zero or more endpoint specific request parameters
* @param urlTemplate request URL template
* @param urlTemplateParams zero or more parameters used with <i>urlTemplate</i>
*/
protected boolean doPostJsonRequest(String adminUser,
String adminPassword,
JSONObject requestParams,
String urlTemplate,
String... urlTemplateParams)
{
AlfrescoHttpClient client = alfrescoHttpClientFactory.getObject();
String requestUrl = MessageFormat.format(
urlTemplate,
client.getApiUrl(),
urlTemplateParams);
client.close();
try
{
return doRequestJson(HttpPost.class, requestUrl, adminUser, adminPassword, requestParams);
}
catch (InstantiationException | IllegalAccessException error)
{
throw new IllegalArgumentException("doPostRequest failed", error);
}
}
/**
* Helper method for handling generic HTTP requests
* @param requestType request type (a subclass of {@link HttpRequestBase})
* @param requestUrl URL the request is to be sent to
* @param adminUser user with administrative privileges
* @param adminPassword password for adminUser
* @param requestParams endpoint specific request parameters
* @return response body
* @throws IllegalAccessException for invalid <i>requestType</i>
* @throws InstantiationException for invalid <i>requestType</i>
*/
private <T extends HttpRequestBase> JSONObject doRequest(
Class<T> requestType,
String requestUrl,
String adminUser,
String adminPassword,
JSONObject requestParams) throws InstantiationException, IllegalAccessException
{
AlfrescoHttpClient client = alfrescoHttpClientFactory.getObject();
T request = requestType.newInstance();
HttpResponse response = null;
JSONObject responseBody = null;
JSONObject returnValues = null;
try
{
request.setURI(new URI(requestUrl));
if (requestParams != null && request instanceof HttpEntityEnclosingRequestBase)
{
((HttpEntityEnclosingRequestBase) request).setEntity(new StringEntity(requestParams.toString()));
}
response = client.execute(adminUser, adminPassword, request);
try
{
responseBody = new JSONObject(EntityUtils.toString(response.getEntity()));
}
catch (ParseException | IOException | JSONException error)
{
LOGGER.error("Parsing message body failed", error);
}
switch (response.getStatusLine().getStatusCode())
{
case HttpStatus.SC_OK:
case HttpStatus.SC_CREATED:
// request successful
if (responseBody != null)
{
returnValues = responseBody;
}
break;
case HttpStatus.SC_INTERNAL_SERVER_ERROR:
case HttpStatus.SC_BAD_REQUEST:
if (responseBody != null && responseBody.has(EXCEPTION_KEY))
{
LOGGER.error("Request failed: " + responseBody.getString(EXCEPTION_KEY));
}
break;
default:
LOGGER.error("Request returned unexpected HTTP status " + response.getStatusLine().getStatusCode());
break;
}
}
catch (JSONException error)
{
LOGGER.error("Unable to extract response parameter", error);
}
catch (UnsupportedEncodingException | URISyntaxException error1)
{
LOGGER.error("Unable to construct request", error1);
}
finally
{
if (request != null)
{
request.releaseConnection();
}
client.close();
}
return returnValues;
}
private <T extends HttpRequestBase> boolean doRequestJson(
Class<T> requestType,
String requestUrl,
String adminUser,
String adminPassword,
JSONObject requestParams) throws InstantiationException, IllegalAccessException
{
AlfrescoHttpClient client = alfrescoHttpClientFactory.getObject();
T request = requestType.newInstance();
try
{
request.setURI(new URI(requestUrl));
request.setHeader("Content-Type", "application/json");
if (requestParams != null && request instanceof HttpEntityEnclosingRequestBase)
{
((HttpEntityEnclosingRequestBase) request).setEntity(new StringEntity(requestParams.toString()));
}
return client.execute(adminUser, adminPassword, request).getStatusLine().getStatusCode() == HttpStatus.SC_OK;
}
catch (UnsupportedEncodingException | URISyntaxException error1)
{
LOGGER.error("Unable to construct request", error1);
}
finally
{
if (request != null)
{
request.releaseConnection();
}
client.close();
}
return false;
}
/**
* Used to set RM items properties
* including records, categories and folders
*/
public enum RMProperty
{
NAME,
TITLE,
CONTENT,
DESCRIPTION,
AUTHOR,
PHYSICAL_SIZE,
NUMBER_OF_COPIES,
STORAGE_LOCATION,
SHELF,
BOX,
FILE,
}
public enum RETENTION_SCHEDULE
{
NAME,
DESCRIPTION,
RETENTION_AUTHORITY,
RETENTION_INSTRUCTIONS,
RETENTION_PERIOD,
RETENTION_LOCATION,
RETENTION_PERIOD_PROPERTY,
RETENTION_GHOST,
RETENTION_ELIGIBLE_FIRST_EVENT,
RETENTION_EVENTS,
}
/**
* Used to execute rm actions on a node
*/
public enum RM_ACTIONS
{
EDIT_DISPOSITION_DATE("editDispositionActionAsOfDate"),
CUT_OFF("cutoff"),
UNDO_CUT_OFF("undoCutoff"),
TRANSFER("transfer"),
DESTROY("destroy");
String action;
private RM_ACTIONS(String action)
{
this.action = action;
}
public String getAction()
{
return action;
}
}
public enum PermissionType
{
SET_READ,
REMOVE_READ,
SET_READ_AND_FILE,
REMOVE_READ_AND_FILE,
}
/**
* Util to return the property value from a map
*
* @param properties the map containing properties
* @param property to get value for
* @return the property value
*/
public <K extends Enum<?>> String getPropertyValue(Map<K, String> properties, Enum<?> property)
{
String value = properties.get(property);
if (value == null)
{
return "";
}
return value;
}
/**
* Retrieves the property value and decides if that gets to be added to the request
*
* @param requestParams the request parameters
* @param propertyRequestValue the property name in the request, eg. "prop_cm_name"
* @param itemProperties map of item's properties values
* @param property the property in the property map to check value for
* @return the json object used in request with the property with its value added if that is not null or empty
*/
protected <K extends Enum<?>> JSONObject addPropertyToRequest(JSONObject requestParams, String propertyRequestValue, Map<K, String> itemProperties, Enum<?> property) throws JSONException
{
String propertyValue = getPropertyValue(itemProperties, property);
if (!propertyValue.equals(""))
{
requestParams.put(propertyRequestValue, propertyValue);
}
return requestParams;
}
/**
* Deletes the category, folder or record given as parameter
*
* @param username the username with whom the delete is performed
* @param password the user's password
* @param itemPath the path to the item eg. in case of a category it would be the "/" + category name,
* in case of a folder or subCategory it would be /categoryName/folderName or /categoryName/subCategoryName/
* in case of a record /categoryName/folderName/recordName
* @return true if the deletion has been successful
*/
protected boolean deleteItem(String username, String password, String itemPath)
{
CmisObject container = getObjectByPath(username, password, FILE_PLAN_PATH + itemPath);
if (container != null)
{
container.delete();
}
return getObjectByPath(username, password, itemPath) == null;
}
}

View File

@@ -0,0 +1,353 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2017 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.v0;
import static org.alfresco.dataprep.AlfrescoHttpClient.MIME_TYPE_JSON;
import java.io.IOException;
import java.text.MessageFormat;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Map;
import org.alfresco.dataprep.AlfrescoHttpClient;
import org.alfresco.dataprep.AlfrescoHttpClientFactory;
import org.alfresco.dataprep.ContentService;
import org.alfresco.dataprep.UserService;
import org.alfresco.rest.core.v0.BaseAPI;
import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
/**
* Methods to make API requests using v0 API on RM items (move, update and other actions) including adding users to RM roles
*
* @author Oana Nechiforescu
* @since 2.5
*/
@Component
public class RMRolesAndActionsAPI extends BaseAPI
{
private static final String RM_ROLES_AUTHORITIES = "{0}rm/roles/{1}/authorities/{2}?alf_ticket={3}";
// logger
private static final Logger LOGGER = LoggerFactory.getLogger(RMRolesAndActionsAPI.class);
private static final String MOVE_ACTIONS_API = "action/rm-move-to/site/rm/documentLibrary/{0}";
private static final String CREATE_HOLDS_API = "{0}type/rma:hold/formprocessor";
/** http client factory */
@Autowired
private AlfrescoHttpClientFactory alfrescoHttpClientFactory;
private ApplicationContext applicationContext;
/** user service */
@Autowired
private UserService userService;
@Autowired
private ContentService contentService;
/**
* create user and assign to records management role
*/
public void createUserAndAssignToRole(
String adminUser,
String adminPassword,
String userName,
String password,
String email,
String role,
String firstName,
String lastName)
{
if (!userService.userExists(adminUser, adminPassword, userName))
{
userService.create(adminUser, adminPassword, userName, password, email, firstName, lastName);
}
assignUserToRole(adminUser, adminPassword, userName, role);
}
/**
* assign user to records management role
*/
public boolean assignUserToRole(String adminUser, String adminPassword, String userName, String role)
{
AlfrescoHttpClient client = alfrescoHttpClientFactory.getObject();
String reqURL = MessageFormat.format(
RM_ROLES_AUTHORITIES,
client.getApiUrl(),
role,
userName,
client.getAlfTicket(adminUser, adminPassword));
HttpPost request = null;
HttpResponse response = null;
try
{
request = new HttpPost(reqURL);
response = client.execute(adminUser, adminPassword, request);
switch (response.getStatusLine().getStatusCode())
{
case HttpStatus.SC_OK:
return true;
case HttpStatus.SC_CONFLICT:
break;
default:
break;
}
}
finally
{
if (request != null)
{
request.releaseConnection();
}
client.close();
}
return false;
}
/**
* Move action
*
* @param user the user to move the contentPath
* @param password the user's password
* @param contentPath path to the content to be moved
* @param destinationPath destination path
* @return true if the action completed successfully
*/
public boolean moveTo(String user, String password, String contentPath, String destinationPath)
{
String contentNodeRef = NODE_REF_WORKSPACE_SPACES_STORE + getItemNodeRef(user, password, contentPath);
AlfrescoHttpClient client = alfrescoHttpClientFactory.getObject();
String url = MessageFormat.format(client.getAlfrescoUrl() + "alfresco/s/slingshot/doclib/" + MOVE_ACTIONS_API, destinationPath);
HttpPost request = new HttpPost(url);
try
{
JSONObject body = new JSONObject();
body.put("nodeRefs", new JSONArray(Arrays.asList(contentNodeRef)));
StringEntity se = new StringEntity(body.toString(), AlfrescoHttpClient.UTF_8_ENCODING);
se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, MIME_TYPE_JSON));
request.setEntity(se);
HttpResponse response = client.execute(user, password, request);
switch (response.getStatusLine().getStatusCode())
{
case HttpStatus.SC_OK:
JSONObject json = new JSONObject(EntityUtils.toString(response.getEntity()));
return (Boolean) json.get("overallSuccess");
case HttpStatus.SC_NOT_FOUND:
LOGGER.info("The provided paths couldn't be found " + response.toString());
default:
LOGGER.error("Unable to move: " + response.toString());
}
}
catch (JSONException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (request != null)
{
request.releaseConnection();
}
client.close();
}
return false;
}
/**
* Perform an action on the record folder
*
* @param user the user executing the action
* @param password the user's password
* @param contentName the content name
* @return true if the action completed successfully
*/
public boolean executeAction(String user, String password, String contentName, RM_ACTIONS rm_action)
{
return executeAction(user, password, contentName, rm_action, null);
}
/**
* Perform an action on the record folder
*
* @param user the user closing the folder
* @param password the user's password
* @param contentName the record folder name
* @param date the date to be updated
* @return true if the action completed successfully
*/
public boolean executeAction(String user, String password, String contentName, RM_ACTIONS action, ZonedDateTime date)
{
String recNodeRef = NODE_REF_WORKSPACE_SPACES_STORE + contentService.getNodeRef(user, password, RM_SITE_ID, contentName);
try
{
JSONObject requestParams = new JSONObject();
requestParams.put("name", action.getAction());
requestParams.put("nodeRef", recNodeRef);
if (date != null)
{
String thisMoment = date.format(DateTimeFormatter.ISO_INSTANT);
requestParams.put("params", new JSONObject()
.put("asOfDate", new JSONObject()
.put("iso8601", thisMoment)
)
);
}
return doPostJsonRequest(user, password, requestParams, RM_ACTIONS_API);
}
catch (JSONException error)
{
LOGGER.error("Unable to extract response parameter", error);
}
return false;
}
/**
* Deletes every item in the given container
*
* @param username the user's username
* @param password its password
* @param siteId the site id in which the container is located
* @param containerName the container to look for items into
* @return true if the deletion has been successful
*/
public boolean deleteAllItemsInContainer(String username, String password, String siteId, String containerName)
{
for (CmisObject item : contentService.getFolderObject(contentService.getCMISSession(username, password), siteId, containerName).getChildren())
{
item.delete();
}
return !(contentService.getFolderObject(contentService.getCMISSession(username, password), siteId, containerName).getChildren().getHasMoreItems());
}
/**
* Deletes hold
*
* @param username user's username
* @param password its password
* @param holdName the hold name
* @return true if the delete is successful
*/
public boolean deleteHold(String username, String password, String holdName)
{
return deleteItem(username, password, "/Holds/" + holdName);
}
/**
* Util method to create a hold
*
* @param user the user creating the category
* @param password the user's password
* @param holdName the hold name
* @param reason hold reason
* @param description hold description
* @return true if the hold creation has been successful
*/
public boolean createHold(String user, String password, String holdName, String reason, String description)
{
// if the hold already exists don't try to create it again
String holdsContainerPath = FILE_PLAN_PATH + "/Holds";
CmisObject hold = getObjectByPath(user, password, holdsContainerPath + "/" + holdName);
if (hold != null)
{
return true;
}
// retrieve the Holds container nodeRef
String parentNodeRef = getItemNodeRef(user, password, "/Holds");
try
{
JSONObject requestParams = new JSONObject();
requestParams.put("alf_destination", NODE_REF_WORKSPACE_SPACES_STORE + parentNodeRef);
requestParams.put("prop_cm_name", holdName);
requestParams.put("prop_cm_description", description);
requestParams.put("prop_rma_holdReason", reason);
boolean requestSucceeded = doPostJsonRequest(user, password, requestParams, CREATE_HOLDS_API);
return requestSucceeded && getObjectByPath(user, password, holdsContainerPath + "/" + holdName) != null;
}
catch (JSONException error)
{
LOGGER.error("Unable to extract response parameter", error);
}
return false;
}
/**
* Updates metadata, can be used on records, folders and categories
*
* @param username the user updating the item
* @param password the user's password
* @param itemNodeRef the item noderef
* @return true if the update of the item properties has been successful
*/
public boolean updateMetadata(String username, String password, String itemNodeRef, Map<RMProperty, String> properties)
{
try
{
JSONObject requestParams = new JSONObject();
addPropertyToRequest(requestParams, "prop_cm_name", properties, RMProperty.NAME);
addPropertyToRequest(requestParams, "prop_cm_title", properties, RMProperty.TITLE);
addPropertyToRequest(requestParams, "prop_cm_description", properties, RMProperty.DESCRIPTION);
addPropertyToRequest(requestParams, "prop_cm_author", properties, RMProperty.AUTHOR);
return doPostJsonRequest(username, password, requestParams, MessageFormat.format(UPDATE_METADATA_API, "{0}", itemNodeRef));
}
catch (JSONException error)
{
LOGGER.error("Unable to extract response parameter", error);
}
return false;
}
}

View File

@@ -0,0 +1,191 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2017 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.v0;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.rest.core.v0.BaseAPI;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* Methods to make API requests using v0 API on record categories
*
* @author Oana Nechiforescu
* @since 2.5
*/
@Component
public class RecordCategoriesAPI extends BaseAPI
{
private static final Logger LOGGER = LoggerFactory.getLogger(RecordCategoriesAPI.class);
private static final String RM_ACTIONS_API = "{0}rma/actions/ExecutionQueue";
private static final String DISPOSITION_ACTIONS_API = "{0}node/{1}/dispositionschedule/dispositionactiondefinitions";
/**
* Creates a retention schedule for the category given as parameter
*
* @param user the user creating the disposition schedule
* @param password the user's password
* @param categoryName the category name to create the retention schedule for
* @return true if the creation completed successfully
*/
public boolean createRetentionSchedule(String user, String password, String categoryName)
{
String catNodeRef = NODE_REF_WORKSPACE_SPACES_STORE + getItemNodeRef(user, password, "/" + categoryName);
try
{
JSONObject requestParams = new JSONObject();
requestParams.put("name", "createDispositionSchedule");
requestParams.put("nodeRef", catNodeRef);
return doPostJsonRequest(user, password, requestParams, RM_ACTIONS_API);
} catch (JSONException error)
{
LOGGER.error("Unable to extract response parameter", error);
}
return false;
}
/**
* Sets retention schedule authority and instructions, also if it is applied to records or folders
*
* @param user the user creating the disposition schedule
* @param password the user's password
* @param retentionNodeRef the retention nodeRef
* @return true if the creation completed successfully
*/
public boolean setRetentionScheduleGeneralFields(String user, String password, String retentionNodeRef, Map<RETENTION_SCHEDULE, String> retentionProperties, Boolean appliedToRecords)
{
String dispRetentionNodeRef = NODE_PREFIX + retentionNodeRef;
try
{
JSONObject requestParams = new JSONObject();
requestParams.put("prop_rma_dispositionAuthority", getPropertyValue(retentionProperties, RETENTION_SCHEDULE.RETENTION_AUTHORITY));
requestParams.put("prop_rma_dispositionInstructions", getPropertyValue(retentionProperties, RETENTION_SCHEDULE.RETENTION_INSTRUCTIONS));
requestParams.put("prop_rma_recordLevelDisposition", appliedToRecords.toString());
return doPostJsonRequest(user, password, requestParams, MessageFormat.format(UPDATE_METADATA_API, "{0}", dispRetentionNodeRef));
} catch (JSONException error)
{
LOGGER.error("Unable to extract response parameter", error);
}
return false;
}
/**
* Creates a retention schedule steps for the category given as parameter
*
* @param user the user creating the disposition schedule
* @param password the user's password
* @param categoryName the category name to create the retention schedule for
* @return true if the creation completed successfully
*/
public boolean addDispositionScheduleSteps(String user, String password, String categoryName, Map<RETENTION_SCHEDULE, String> properties)
{
String catNodeRef = NODE_PREFIX + getItemNodeRef(user, password, "/" + categoryName);
{
try
{
JSONObject requestParams = new JSONObject();
addPropertyToRequest(requestParams, "name", properties, RETENTION_SCHEDULE.NAME);
addPropertyToRequest(requestParams, "description", properties, RETENTION_SCHEDULE.DESCRIPTION);
addPropertyToRequest(requestParams, "period", properties, RETENTION_SCHEDULE.RETENTION_PERIOD);
addPropertyToRequest(requestParams, "ghostOnDestroy", properties, RETENTION_SCHEDULE.RETENTION_GHOST);
addPropertyToRequest(requestParams, "periodProperty", properties, RETENTION_SCHEDULE.RETENTION_PERIOD_PROPERTY);
addPropertyToRequest(requestParams, "events", properties, RETENTION_SCHEDULE.RETENTION_EVENTS);
addPropertyToRequest(requestParams, "eligibleOnFirstCompleteEvent", properties, RETENTION_SCHEDULE.RETENTION_ELIGIBLE_FIRST_EVENT);
return doPostJsonRequest(user, password, requestParams, MessageFormat.format(DISPOSITION_ACTIONS_API, "{0}", catNodeRef));
} catch (JSONException error)
{
LOGGER.error("Unable to extract response parameter", error);
}
return false;
}
}
/**
* Delete a category
*
* @param username user's username
* @param password its password
* @param categoryName the name of the category
* @return true if the delete is successful
*/
public boolean deleteCategory(String username, String password, String categoryName)
{
return deleteItem(username, password, "/" + categoryName);
}
/**
* Delete a sub-category
*
* @param username user's username
* @param password its password
* @param categoryName the name of the sub-category
* @return true if the delete is successful
*/
public boolean deleteSubCategory(String username, String password, String categoryName, String subCategoryName)
{
return deleteItem(username, password, "/" + categoryName + "/" + subCategoryName);
}
/**
* Delete a folder inside a container in RM site
*
* @param username user's username
* @param password its password
* @param folderName folder name
* @param containerName the name of the category or container sin which the folder is
* @return true if the delete is successful
*/
public boolean deleteFolderInContainer(String username, String password, String folderName, String containerName)
{
return deleteItem(username, password, "/" + containerName + "/" + folderName);
}
/**
* Returns a map of retention properties
*
* @param authority retention authority
* @param instructions retention authority
* @return the map
*/
public Map<RETENTION_SCHEDULE, String> getRetentionProperties(String authority, String instructions)
{
Map<RETENTION_SCHEDULE, String> retentionProperties = new HashMap<>();
retentionProperties.put(RETENTION_SCHEDULE.RETENTION_AUTHORITY, authority);
retentionProperties.put(RETENTION_SCHEDULE.RETENTION_INSTRUCTIONS, instructions);
return retentionProperties;
}
}

View File

@@ -0,0 +1,78 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2017 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.v0;
import org.alfresco.dataprep.ContentService;
import org.alfresco.rest.core.v0.BaseAPI;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Methods to make API requests using v0 API on records folders
*
* @author Oana Nechiforescu
* @since 2.5
*/
@Component
public class RecordFoldersAPI extends BaseAPI
{
private static final Logger LOGGER = LoggerFactory.getLogger(RecordFoldersAPI.class);
@Autowired
private ContentService contentService;
/**
* Close the record folder
*
* @param user the user closing the folder
* @param password the user's password
* @param recordFolder the record folder name
* @return true if the action completed successfully
*/
public boolean closeRecordFolder(String user, String password, String recordFolder)
{
String recNodeRef = NODE_REF_WORKSPACE_SPACES_STORE + contentService.getNodeRef(user, password, RM_SITE_ID, recordFolder);
try
{
JSONObject requestParams = new JSONObject();
requestParams.put("name", "closeRecordFolder");
requestParams.put("nodeRef", recNodeRef);
return doPostJsonRequest(user, password, requestParams, RM_ACTIONS_API);
}
catch (JSONException error)
{
LOGGER.error("Unable to extract response parameter", error);
}
return false;
}
}

View File

@@ -0,0 +1,291 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2017 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.v0;
import java.util.Map;
import org.alfresco.dataprep.CMISUtil.DocumentType;
import org.alfresco.dataprep.ContentService;
import org.alfresco.rest.core.v0.BaseAPI;
import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Methods to make API requests using v0 API on records
*
* @author Oana Nechiforescu
* @since 2.5
*/
@Component
public class RecordsAPI extends BaseAPI
{
// logger
private static final Logger LOGGER = LoggerFactory.getLogger(RecordsAPI.class);
private static final String CREATE_NON_ELECTRONIC_RECORD_API = "{0}type/rma:nonElectronicDocument/formprocessor";
@Autowired
private ContentService contentService;
/**
* Declare documents as records
*
* @param user the user declaring the document as record
* @param password the user's password
* @param siteID the site id in which the document exists
* @param documentName the document name
* @return true if the action was successful
*/
public boolean declareDocumentAsRecord(String user, String password, String siteID, String documentName)
{
String docNodeRef = NODE_REF_WORKSPACE_SPACES_STORE + contentService.getNodeRef(user, password, siteID, documentName);
try
{
JSONObject requestParams = new JSONObject();
requestParams.put("actionedUponNode", docNodeRef);
requestParams.put("actionDefinitionName", "create-record");
return doPostJsonRequest(user, password, requestParams, ACTIONS_API);
}
catch (JSONException error)
{
LOGGER.error("Unable to extract response parameter", error);
}
return false;
}
/**
* Completes the record given as parameter
*
* @param user the user declaring the document as record
* @param password the user's password
* @param recordName the record name
* @return true if the action completed successfully
*/
public boolean completeRecord(String user, String password, String recordName)
{
String recNodeRef = NODE_REF_WORKSPACE_SPACES_STORE + contentService.getNodeRef(user, password, RM_SITE_ID, recordName);
try
{
JSONObject requestParams = new JSONObject();
requestParams.put("name", "declareRecord");
requestParams.put("nodeRef", recNodeRef);
return doPostJsonRequest(user, password, requestParams, RM_ACTIONS_API);
}
catch (JSONException error)
{
LOGGER.error("Unable to extract response parameter", error);
}
return false;
}
/**
* Declare document version as record
*
* @param user the user declaring the document version as record
* @param password the user's password
* @param siteID the site id in which the document exists
* @param documentName the document name
* @return true if the action was successful
*/
public boolean declareDocumentVersionAsRecord(String user, String password, String siteID, String documentName)
{
String docNodeRef = NODE_REF_WORKSPACE_SPACES_STORE + contentService.getNodeRef(user, password, siteID, documentName);
try
{
JSONObject requestParams = new JSONObject();
requestParams.put("actionedUponNode", docNodeRef);
requestParams.put("actionDefinitionName", "declare-as-version-record");
return doPostJsonRequest(user, password, requestParams, ACTIONS_API);
}
catch (JSONException error)
{
LOGGER.error("Unable to extract response parameter", error);
}
return false;
}
/**
* Creates a non-electronic record
*
* @param username the username
* @param password the password
* @param properties a map of record properties and their values
* @param categoryName the category that contains the record, in the case in which the container would be Unfiled records use UNFILED_RECORDS_BREADCRUMB as value
* @param folderName the folder inside which the record exists, in the case in which the folder name is "", the record will be created directly in the specified container
* this case is useful when trying to create a record directly in Unfiled Records
* @return true if the creation of the record has been successful
* eg. of usage for Unfiled records with folder : createNonElectronicRecord(getAdminName(), getAdminPassword(), properties, UNFILED_RECORDS_BREADCRUMB, "unfiled records folder");
* eg. of usage for creating record directly in Unfiled Records : createNonElectronicRecord(getAdminName(), getAdminPassword(), properties, UNFILED_RECORDS_BREADCRUMB, "");
*/
public <K extends Enum<?>> boolean createNonElectronicRecord(String username, String password, Map<K, String> properties, String categoryName, String folderName)
{
String recordName = properties.get(RMProperty.NAME);
if (getRecord(username, password, folderName, recordName) != null)
{
return true;
}
String recordPath = "/" + categoryName;
if (!folderName.equals(""))
{
recordPath = recordPath + "/" + folderName;
}
// if the record already exists don't try to create it again
CmisObject record = getObjectByPath(username, password, FILE_PLAN_PATH + recordPath + "/" + recordName);
if (record != null)
{
return true;
}
// non-electronic properties
String recordTitle = getPropertyValue(properties, RMProperty.TITLE);
String description = getPropertyValue(properties, RMProperty.DESCRIPTION);
String physicalSize = getPropertyValue(properties, RMProperty.PHYSICAL_SIZE);
String numberOfCopies = getPropertyValue(properties, RMProperty.NUMBER_OF_COPIES);
String shelf = getPropertyValue(properties, RMProperty.SHELF);
String storage = getPropertyValue(properties, RMProperty.STORAGE_LOCATION);
String box = getPropertyValue(properties, RMProperty.BOX);
String file = getPropertyValue(properties, RMProperty.FILE);
// retrieve the container nodeRef
String parentNodeRef = getItemNodeRef(username, password, recordPath);
try
{
JSONObject requestParams = new JSONObject();
requestParams.put("alf_destination", NODE_REF_WORKSPACE_SPACES_STORE + parentNodeRef);
requestParams.put("prop_cm_name", recordName);
requestParams.put("prop_cm_title", recordTitle);
requestParams.put("prop_cm_description", description);
requestParams.put("prop_rma_physicalSize", physicalSize);
requestParams.put("prop_rma_numberOfCopies", numberOfCopies);
requestParams.put("prop_rma_storageLocation", storage);
requestParams.put("prop_rma_shelf", shelf);
requestParams.put("prop_rma_box", box);
requestParams.put("prop_rma_file", file);
return doPostJsonRequest(username, password, requestParams, CREATE_NON_ELECTRONIC_RECORD_API);
} catch (JSONException error)
{
LOGGER.error("Unable to extract response parameter", error);
}
return false;
}
/**
* Uploads an electronic record
*
* @param username the username
* @param password the password
* @param properties a map of record properties and their values
* @param folderName the folder inside which the record will be created, it needs to have a unique name
* @return true if the creation of the record has been successful
* eg. of usage for creating record directly in Unfiled Records : uploadElectronicRecord(getAdminName(), getAdminPassword(), recordPropertiesStringMap, UNFILED_RECORDS_BREADCRUMB, DocumentType.HTML)
* the folder name in which the record gets created has to have a unique name, as this method doesn't check other containers than the folder name
*/
public boolean uploadElectronicRecord(String username, String password, Map<RMProperty, String> properties, String folderName, DocumentType documentType)
{
String recordName = getPropertyValue(properties, RMProperty.NAME);
String recordContent = getPropertyValue(properties, RMProperty.CONTENT);
return (getRecord(username, password, folderName, recordName) != null) || (contentService.createDocumentInFolder(username, password, RM_SITE_ID, folderName, documentType, recordName, recordContent) != null);
}
/**
* Delete a record from the given path
*
* @param username user's username
* @param password its password
* @param recordName the record name
* @param categoryName the name of the category in which the folder is, in case of unfiled record, this will have UNFILED_RECORDS_BREADCRUMB as container
* @param folderName folder name, in case in which trying to delete a record in Unfiled records directly, this will be ""
* @return true if the delete is successful
* eg. of usage in the case in which the record is inside a folder in Unfiled Records : deleteRecord(getAdminName(), getAdminPassword(), "f1 (2016-1472716888713)", UNFILED_RECORDS_BREADCRUMB, "unfiled records folder");
* eg. of usage in the case in which the record is created directly in Unfiled Records : deleteRecord(getAdminName(), getAdminPassword(), "f1 (2016-1472716888713)", UNFILED_RECORDS_BREADCRUMB, "");
*/
public boolean deleteRecord(String username, String password, String recordName, String categoryName, String folderName)
{
String recordPath = "/" + categoryName;
if (!folderName.equals(""))
{
recordPath = recordPath + "/" + folderName;
}
return deleteItem(username, password, recordPath + "/" + recordName);
}
/**
* Retrieves the record object in case it exists
*
* @param username the user's username
* @param password its password
* @param folderName the folder in which the record is supposed to exist
* @param recordName the String with which the record name starts
* @return the record object in case it exists, null otherwise
*/
private CmisObject getRecord(String username, String password, String folderName, String recordName)
{
for (CmisObject record : contentService.getFolderObject(contentService.getCMISSession(username, password), RM_SITE_ID, folderName).getChildren())
{
if (record.getName().startsWith(recordName))
{
return record;
}
}
return null;
}
/**
* Retrieves record full name for given partial name
*
* @param username the user's username
* @param password its password
* @param folderName the folder in which the record is supposed to exist
* @param recordPartialName the String with which the record name starts
* @return the record name in case it exists, empty String otherwise
*/
public String getRecordFullName(String username, String password, String folderName, String recordPartialName)
{
CmisObject record = getRecord(username, password, folderName, recordPartialName);
if (record != null)
{
return record.getName();
}
return "";
}
}

View File

@@ -0,0 +1,177 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2017 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.v0;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.alfresco.dataprep.AlfrescoHttpClientFactory;
import org.alfresco.rest.core.v0.BaseAPI;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Helper methods for performing search using various Alfresco search APIs.
*
* @author Kristijan Conkas
* @since 2.5
*/
@Component
public class SearchAPI extends BaseAPI
{
/** http client factory */
@Autowired private AlfrescoHttpClientFactory alfrescoHttpClientFactory;
/** faceted search API endpoint */
private static final String FACETED_SEARCH_ENDPOINT = "{0}alfresco/s/slingshot/rmsearch/faceted/rmsearch?{1}";
/** RM search URL template */
private static final String RM_SEARCH_ENDPOINT = "{0}alfresco/s/slingshot/rmsearch/{1}?{2}";
/** RM document search filters */
private static final String RM_DEFAULT_RECORD_FILTERS =
"records/true,undeclared/true,vital/false,folders/false,categories/false,frozen/false,cutoff/false";
/**
* Perform search request on search endpoint as a user.
* <p>
* This method is applicable only to endpoints that support HTTP GET requests and return JSON body as response.
* @param searchEndpoint
* @param searchUser
* @param searchPassword
* @return search results as a {@link JSONObject}, please refer to API documentation for details
*/
private JSONObject doSearch(
String searchEndpoint,
String searchUser,
String searchPassword)
{
return facetedRequest(searchUser, searchPassword, null, searchEndpoint);
}
/**
* Generic rm search.
* @param username
* @param password
* @param site
* @param query
* @param filters
* @return search results (see API reference for more details), null for any errors
*/
public JSONObject rmSearch(
String username,
String password,
String site,
String query,
String filters)
{
List<BasicNameValuePair> searchParameters = new ArrayList<BasicNameValuePair>();
searchParameters.add(new BasicNameValuePair("query", query));
searchParameters.add(new BasicNameValuePair("filters", filters));
String requestURL = MessageFormat.format(
RM_SEARCH_ENDPOINT,
alfrescoHttpClientFactory.getObject().getAlfrescoUrl(),
(site != null) ? site : RM_SITE_ID,
URLEncodedUtils.format(searchParameters, "UTF-8"));
return doSearch(requestURL, username, password);
}
/**
* Search as a user for records on site "rm" matching query, using SearchAPI.RM_DEFAULT_RECORD_FILTERS
* <br>
* If more fine-grained control of search parameters is required, use rmSearch() directly.
* @param username
* @param password
* @param query
* @return list of record names
*/
public List<String> searchForRecordsAsUser(
String username,
String password,
String query)
{
return getItemNames(rmSearch(username, password, "rm", query, RM_DEFAULT_RECORD_FILTERS));
}
/**
* Generic faceted search.
* @param username
* @param password
* @param parameters
* @return search results (see API reference for more details), null for any errors
*/
public JSONObject facetedSearch(String username, String password, List<NameValuePair> parameters)
{
return facetedRequest(username, password, parameters, FACETED_SEARCH_ENDPOINT);
}
/**
* Execute faceted search for term.
* @param searchUser
* @param searchPassword
* @param searchTerm
* @return search results (see API reference for more details)
*/
public JSONObject facetedSearchForTerm(String searchUser, String searchPassword, String searchTerm)
{
return facetedSearch(
searchUser,
searchPassword,
Arrays.asList(new BasicNameValuePair("term", searchTerm)));
}
/**
* Helper method to search for documents as a user using faceted search.
* @param username to search as
* @param password for username
* @param term search term
* @return list of document names found
*/
public List<String> searchForDocumentsAsUser(String username, String password, String term)
{
return getItemNames(facetedSearchForTerm(username, password, term));
}
/**
* Helper method to extract list of names from search result.
* @param searchResult
* @return list of document or record names in search result
* @throws RuntimeException for malformed search response
*/
private List<String> getItemNames(JSONObject searchResult)
{
return getPropertyValues(searchResult, "name");
}
}