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");
+ }
+}