diff --git a/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/rules/ActionsOnRule.java b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/rules/ActionsOnRule.java new file mode 100644 index 0000000000..91f185795d --- /dev/null +++ b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/rules/ActionsOnRule.java @@ -0,0 +1,65 @@ +/* + * #%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 . + * #L% + */ +package org.alfresco.rest.rm.community.model.rules; + +/** + * Action values. + */ +public enum ActionsOnRule +{ + COMPLETE_RECORD("declareRecord"), + REOPEN_RECORD("undeclareRecord"), + OPEN_RECORD_FOLDER("openRecordFolder"), + CLOSE_RECORD_FOLDER("closeRecordFolder"), + FILE_TO("fileTo"), + COPY_TO("copyTo"), + MOVE_TO("moveTo"), + LINK_TO("linkTo"), + REJECT("reject"), + REQUEST_INFORMATION("requestInfo"), + COMPLETE_EVENT("completeEvent"), + ADD_RECORD_TYPES("addRecordTypes"), + EXECUTE_SCRIPT("executeScript"), + SEND_EMAIL("sendEmail"), + SET_PROPERTY_VALUE_COLL_SITE("set-property-value"), + SET_PROPERTY_VALUE_RM("setPropertyValue"), + HIDE_RECORD("hide-record"), + DECLARE_VERSION_AS_RECORD("declare-as-version-record"), + DECLARE_AS_RECORD("create-record"); + + private String actionValue; + + ActionsOnRule(String value) + { + this.actionValue = value; + } + + public String getActionValue() + { + return actionValue; + } +} diff --git a/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/rules/ConditionsOnRule.java b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/rules/ConditionsOnRule.java new file mode 100644 index 0000000000..00421a94de --- /dev/null +++ b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/rules/ConditionsOnRule.java @@ -0,0 +1,48 @@ +/* + * #%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 . + * #L% + */ +package org.alfresco.rest.rm.community.model.rules; + +/** + * enum used to find the when condition names options by their value + */ +public enum ConditionsOnRule +{ + UPDATE("update"), + ADDED("inbound"), + REMOVED("outbound"); + private String whenConditionValue; + + ConditionsOnRule(String value) + { + this.whenConditionValue = value; + } + + public String getWhenConditionValue() + { + return whenConditionValue; + } +} diff --git a/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/rules/RuleDefinition.java b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/rules/RuleDefinition.java new file mode 100644 index 0000000000..d271a372cd --- /dev/null +++ b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/rules/RuleDefinition.java @@ -0,0 +1,203 @@ +/* + * #%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 . + * #L% + */ +package org.alfresco.rest.rm.community.model.rules; + +import java.util.List; + +/** + * A class describing the rule + */ +public class RuleDefinition +{ + private String id = ""; + private String title; + private String description = ""; + private boolean disabled = false; + private boolean applyToChildren = false; + private boolean runInBackground = false; + private String ruleType = ConditionsOnRule.ADDED.getWhenConditionValue(); + private String path; + private boolean createRecordPath = false; + private String contentTitle; + private String contentDescription; + private String rejectReason; + private List actions; + + /** + * Creates a new object of type Rule Definition + * + * @return the object + */ + public static RuleDefinition createNewRule() + { + return new RuleDefinition(); + } + + public String getId() + { + return id; + } + + public RuleDefinition id(String id) + { + this.id = id; + return this; + } + + public String getTitle() + { + return title; + } + + public RuleDefinition title(String title) + { + this.title = title; + return this; + } + + public String getDescription() + { + return description; + } + + public RuleDefinition description(String description) + { + this.description = description; + return this; + } + + public boolean isDisabled() + { + return disabled; + } + + public RuleDefinition disabled(boolean disabled) + { + this.disabled = disabled; + return this; + } + + public boolean isApplyToChildren() + { + return applyToChildren; + } + + public RuleDefinition applyToChildren(boolean applyToChildren) + { + this.applyToChildren = applyToChildren; + return this; + } + + public boolean getRunInBackground() + { + return runInBackground; + } + + public RuleDefinition runInBackground(boolean runInBackground) + { + this.runInBackground = runInBackground; + return this; + } + + public String getRuleType() + { + return ruleType; + } + + public RuleDefinition ruleType(String ruleType) + { + this.ruleType = ruleType; + return this; + } + + public String getPath() + { + return path; + } + + public RuleDefinition path(String path) + { + this.path = path; + return this; + } + + public boolean isCreateRecordPath() + { + return createRecordPath; + } + + public RuleDefinition createRecordPath(boolean createRecordPath) + { + this.createRecordPath = createRecordPath; + return this; + } + + public String getContentTitle() + { + return contentTitle; + } + + public RuleDefinition contentTitle(String contentTitle) + { + this.contentTitle = contentTitle; + return this; + } + + public String getContentDescription() + { + return contentDescription; + } + + public RuleDefinition contentDescription(String contentDescription) + { + this.contentDescription = contentDescription; + return this; + } + + public String getRejectReason() + { + return rejectReason; + } + + public RuleDefinition rejectReason(String rejectReason) + { + this.rejectReason = rejectReason; + return this; + } + + + public List getActions() + { + return actions; + } + + public RuleDefinition actions(List actions) + { + this.actions = actions; + return this; + } +} diff --git a/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/RulesAPI.java b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/RulesAPI.java new file mode 100644 index 0000000000..00704081da --- /dev/null +++ b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/RulesAPI.java @@ -0,0 +1,369 @@ +/* + * #%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 . + * #L% + */ + +package org.alfresco.rest.v0; + +import static java.util.Arrays.asList; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.alfresco.rest.core.v0.BaseAPI; +import org.alfresco.rest.rm.community.model.rules.ActionsOnRule; +import org.alfresco.rest.rm.community.model.rules.RuleDefinition; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * Covers CRUD API operations on rules + */ +@Component +public class RulesAPI extends BaseAPI +{ + + public static final String RULES_API = "{0}node/{1}/ruleset/rules"; + public static final String RULE_API = "{0}node/{1}/ruleset/rules/{2}"; + public static final String INHERIT_RULES_API = "{0}node/{1}/ruleset/inheritrules/toggle"; + public static final String INHERIT_RULES_STATE_API = "{0}node/{1}/ruleset/inheritrules/state"; + // logger + public static final Logger LOGGER = LoggerFactory.getLogger(RulesAPI.class); + + /** + * Creates a rule for the specified container with given rule properties + * + * @param containerNodeRef the container to have the rule created on + * @param ruleProperties the rule properties + * @return true if the rule has been created successfully, false otherwise + */ + + public boolean createRule(String username, String password, String containerNodeRef, RuleDefinition ruleProperties) + { + try + { + return doPostJsonRequest(username, password, getRuleRequest(ruleProperties), MessageFormat.format(RULES_API, "{0}", containerNodeRef)); + } + catch (JSONException error) + { + LOGGER.error("Unable to extract response parameter.", error); + } + return false; + } + + /** + * Updates a rule for the specified container with given rule properties + * + * @param containerNodeRef the container to have the rule created on + * @param ruleProperties the rule properties + * @return true if the rule has been updated successfully, false otherwise + */ + + public JSONObject updateRule(String username, String password, String containerNodeRef, RuleDefinition ruleProperties) + { + String ruleId = ruleProperties.getId(); + if (ruleId == null || ruleId.isEmpty()) + { + throw new RuntimeException("Can not update a rule without id."); + } + try + { + return doPutRequest(username, password, getRuleRequest(ruleProperties), MessageFormat.format(RULE_API, "{0}", containerNodeRef, ruleId)); + } + catch (JSONException error) + { + LOGGER.error("Unable to extract response parameter.", error); + } + return null; + } + + /** + * Deletes a rule on a container and checks it doesn't exist anymore + * + * @param username the user performing the request + * @param password the password + * @param containerNodeRef the container on which the rule has been created + * @param ruleId the rule id + * @return true if the rule is deleted successfully + */ + public boolean deleteRule(String username, String password, String containerNodeRef, String ruleId) + { + doDeleteRequest(username, password, MessageFormat.format(RULE_API, "{0}", containerNodeRef, ruleId)); + return !getRulesIdsSetOnContainer(username, password, containerNodeRef).contains(ruleId); + } + + /** + * Deletes all the rules on a container and checks they don't exist anymore + * + * @param username the user performing the request + * @param password the password + * @param containerNodeRef the container on which the rules have been created + * @return true if the rules are deleted successfully + */ + public boolean deleteAllRulesOnContainer(String username, String password, String containerNodeRef) + { + boolean allDeleted = false; + List ruleIds = getRulesIdsSetOnContainer(username, password, containerNodeRef); + + if(ruleIds.isEmpty()) + { + return true; + } + for (String ruleId : ruleIds) + { + allDeleted = deleteRule(username, password, containerNodeRef, ruleId); + } + return allDeleted; + } + + /** + * Gets all the rules for the specified container with given rule properties + * + * @param username the user performing the request + * @param password the password + * @param containerNodeRef the container to get the rules from + * + * @return list of rules on container + */ + + public List getRulesSetOnContainer(String username, String password, String containerNodeRef) + { + List rulesDefinitions = new ArrayList<>(); + + // get the rules set on the container + JSONObject rulesJson = doGetRequest(username, password, MessageFormat.format(RULES_API, "{0}", containerNodeRef)); + if (rulesJson != null) + { + try + { + JSONArray rules = rulesJson.getJSONArray("data"); + for (int i = 0; i < rules.length(); i++) + { + RuleDefinition ruleDefinition = new RuleDefinition(); + JSONObject rule = rules.getJSONObject(i); + ruleDefinition.id(rule.getString("id")); + ruleDefinition.title(rule.getString("title")); + ruleDefinition.description(rule.getString("description")); + ruleDefinition.ruleType(rule.getJSONArray("ruleType").get(0).toString()); + ruleDefinition.disabled(rule.getBoolean("disabled")); + rulesDefinitions.add(ruleDefinition); + } + } + catch (JSONException error) + { + LOGGER.error("Unable to parse rules.", error); + } + } + return rulesDefinitions; + } + + /** + * Retrieves all the ids of the rules set on the container + * + * @param username the user performing the request + * @param password the password + * @param containerNodeRef the container's noderef to get set rules for + * @return the list of rules ids that the container has + */ + public List getRulesIdsSetOnContainer(String username, String password, String containerNodeRef) + { + return getRulesSetOnContainer(username, password, containerNodeRef).stream().map(RuleDefinition::getId).collect(Collectors.toList()); + } + + /** + * Prepares a request object for rules with given properties + * + * @param ruleProperties the rule properties + * @return a object containing the rule properties for the request + * + * @throws JSONException + */ + private JSONObject getRuleRequest(RuleDefinition ruleProperties) throws JSONException + { + JSONObject requestParams = new JSONObject(); + + // the id has to be sent as empty string no matter the request + requestParams.put("id", ""); + requestParams.put("action", addRulesActions(ruleProperties)); + requestParams.put("title", ruleProperties.getTitle()); + requestParams.put("description", ruleProperties.getDescription()); + requestParams.put("disabled", ruleProperties.isDisabled()); + requestParams.put("applyToChildren", ruleProperties.isApplyToChildren()); + requestParams.put("executeAsynchronously", ruleProperties.getRunInBackground()); + requestParams.put("ruleType", asList(ruleProperties.getRuleType())); + + return requestParams; + } + + /** + * Adds rules actions to the request + * + * @param ruleProperties the rules properties to extract actions from + * + * @return the object with actions set + * + * @throws JSONException + */ + private JSONObject addRulesActions(RuleDefinition ruleProperties) throws JSONException + { + JSONObject action = new JSONObject(); + action.put("actionDefinitionName", "composite-action"); + JSONObject conditions = new JSONObject(); + conditions.put("conditionDefinitionName", "no-condition"); + conditions.put("parameterValues", new JSONObject()); + action.put("conditions", asList(conditions)); + action.put("actions", getRuleActionsList(ruleProperties)); + return action; + } + + /** + * Creates the actions list for request + * + * @param ruleProperties given rule properties + * + * @return the list of rule actions objects + */ + private List getRuleActionsList(RuleDefinition ruleProperties) throws JSONException + { + List ruleActionsList = new ArrayList<>(); + + for (ActionsOnRule ruleAction : ruleProperties.getActions()) + { + JSONObject ruleActionObj = new JSONObject(); + ruleActionObj.put("actionDefinitionName", ruleAction.getActionValue()); + JSONObject parameters = new JSONObject(); + if (ruleProperties.getPath() != null) + { + parameters.put("createRecordPath", ruleProperties.isCreateRecordPath()); + parameters.put("path", ruleProperties.getPath()); + } + if (ruleProperties.getContentTitle() != null) + { + parameters.put("property", "cm:title"); + parameters.put("value", ruleProperties.getContentTitle()); + parameters.put("prop_type", "d:mltext"); + } + if (ruleProperties.getContentDescription() != null) + { + parameters.put("property", "cm:description"); + parameters.put("value", ruleProperties.getContentDescription()); + parameters.put("prop_type", "d:mltext"); + } + if (ruleProperties.getRejectReason() != null) + { + parameters.put("reason", ruleProperties.getRejectReason()); + } + ruleActionObj.put("parameterValues", parameters); + ruleActionsList.add(ruleActionObj); + } + return ruleActionsList; + } + + /** + * Returns the rule id for the give rule title set on a container + * + * @param username the user performing the request + * @param password the password + * @param containerNodeRef container nodeRef + * + * @return the rule id + */ + public String getRuleIdWithTitle(String username, String password, String containerNodeRef, String title) + { + return getRulesSetOnContainer(username, password, containerNodeRef).stream().filter( + rule -> rule.getTitle().equals(title)).findAny().get().getId(); + } + + /** + * Disable inheritance on specific container + * + * @param username the username + * @param password the password + * @param containerNodeRef the container nodeRef + * + * @return true if the rule has been disabled or if the current state is disabled + */ + public boolean disableRulesInheritance(String username, String password, String containerNodeRef) + { + try + { + if(containerInheritsRulesFromParent(username, password, containerNodeRef)) + { + return doPostJsonRequest(username, password, new JSONObject(), MessageFormat.format(INHERIT_RULES_API, "{0}", containerNodeRef)); + } + } + catch (JSONException e) + { + return false; + } + return true; + } + + /** + * Enable inheritance on specific container + * + * @param username the username + * @param password the password + * @param containerNodeRef the container nodeRef + * @return true if the rule has been enabled or if the current state is enabled + */ + public boolean enableRulesInheritance(String username, String password, String containerNodeRef) + { + try + { + if (!containerInheritsRulesFromParent(username, password, containerNodeRef)) + { + return doPostJsonRequest(username, password, new JSONObject(), MessageFormat.format(INHERIT_RULES_API, "{0}", containerNodeRef)); + } + } + catch (JSONException e) + { + return false; + } + return true; + } + + /** + * Returns the rules inheritance state of the container + * + * @param username the username + * @param password the password + * @param containerNodeRef the container nodeRef + * + * @return a boolean specifying if the container inherits rules from parent + * @throws JSONException + */ + public boolean containerInheritsRulesFromParent(String username, String password, String containerNodeRef) throws JSONException + { + JSONObject rulesInheritanceInfo = doGetRequest(username, password, MessageFormat.format(INHERIT_RULES_STATE_API, "{0}", containerNodeRef)); + return rulesInheritanceInfo.getJSONObject("data").getBoolean("inheritRules"); + } +}