Rules/Actions REST API drop after current phase of testing

- various minor fixes from current testing phase
- various code improvements, mostly in Rules Helper JSON to object translation methods for rules, actions and conditions
- some improvements to test data creation in unit test class helper methods
- updates to delete, get, post rule unit tests
- put rule unit test
- finer grained per property JSON exception handling in rules helper methods
- added more assertions to various unit tests
- added more comments to web scripts and rules helper methods
- added more comments to unit tests
- added more error checking across various web scripts


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@11483 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Glen Johnson
2008-10-22 17:52:25 +00:00
parent a2ea16b286
commit f784bfc7f8
10 changed files with 907 additions and 384 deletions

View File

@@ -1,9 +1,9 @@
<webscript> <webscript>
<shortname>Get Rule</shortname> <shortname>Get Rule</shortname>
<description>Get the rule identified by the specified rule node reference.</description> <description>Get the rule identified by the specified rule node reference.</description>
<url>/api/rules/{store_type}/{store_id}/{id}</url> <url>/api/rules/{store_type}/{store_id}/{rule_id}</url>
<url>/api/node/{store_type}/{store_id}/{id}/rules/{id}</url> <url>/api/node/{store_type}/{store_id}/{id}/rules/{rule_id}</url>
<url>/api/path/{store_type}/{store_id}/{id}/rules/{id}</url> <url>/api/path/{store_type}/{store_id}/{id}/rules/{rule_id}</url>
<format default="json"/> <format default="json"/>
<authentication>user</authentication> <authentication>user</authentication>
<transaction>required</transaction> <transaction>required</transaction>

View File

@@ -1,9 +1,9 @@
<webscript> <webscript>
<shortname>Put Rule</shortname> <shortname>Put Rule</shortname>
<description>Update the rule identified by the specified rule node reference.</description> <description>Update the rule identified by the specified rule node reference.</description>
<url>/api/rules/{store_type}/{store_id}/{id}</url> <url>/api/rules/{store_type}/{store_id}/{rule_id}</url>
<url>/api/node/{store_type}/{store_id}/{id}/rules/{id}</url> <url>/api/node/{store_type}/{store_id}/{id}/rules/{rule_id}</url>
<url>/api/path/{store_type}/{store_id}/{id}/rules/{id}</url> <url>/api/path/{store_type}/{store_id}/{id}/rules/{rule_id}</url>
<format default="json"/> <format default="json"/>
<authentication>user</authentication> <authentication>user</authentication>
<transaction>required</transaction> <transaction>required</transaction>

View File

@@ -1,2 +1,2 @@
<#import "rule.lib.ftl" as ruleLib/> <#import "rule.lib.ftl" as ruleLib/>
<@ruleLib.ruleJSON rule=rule/> <@ruleLib.ruleJSON rule=rule owningNodeRef=owningNodeRef/>

View File

@@ -37,6 +37,16 @@ import org.alfresco.web.scripts.WebScriptRequest;
/** /**
* Web Script to DELETE the rule identified by the given rule node id. * Web Script to DELETE the rule identified by the given rule node id.
* *
* NOTE -
* that if a value is provided for the 'id' URL template variable {id},
* i.e. either of the following URL patterns have been used
* <url>/api/node/{store_type}/{store_id}/{id}/rules/{rule_id}</url> or
* <url>/api/path/{store_type}/{store_id}/{id}/rules/{rule_id}</url>
* then the rule owning node ref supplied therein will be ignored,
* as these URL templates are just provided for convenience and the
* rule owning node ref is retrieved by using the rule's identifying node
* ref (supplied in {rule_id})
*
* @author glen johnson at alfresco dot com * @author glen johnson at alfresco dot com
*/ */
public class RuleDelete extends DeclarativeWebScript public class RuleDelete extends DeclarativeWebScript
@@ -100,28 +110,25 @@ public class RuleDelete extends DeclarativeWebScript
} }
String ruleNodeId = req.getServiceMatch().getTemplateVars().get(REQ_TEMPL_VAR_RULE_NODE_ID); String ruleNodeId = req.getServiceMatch().getTemplateVars().get(REQ_TEMPL_VAR_RULE_NODE_ID);
// Handle if 'ruleNodeId' URL template token not provided // Handle if 'rule_id' URL template token not provided
if ((ruleNodeId == null) || (ruleNodeId.length() == 0)) if ((ruleNodeId == null) || (ruleNodeId.length() == 0))
{ {
throw new WebScriptException(Status.STATUS_BAD_REQUEST, throw new WebScriptException(Status.STATUS_BAD_REQUEST,
"The 'rule_id' URL template token has not been provided in URL"); "The 'rule_id' URL template token has not been provided in URL");
} }
// NOTE -
// that if a value is provided for the 'id' URL template variable {id},
// i.e. either of the following URL patterns have been used
// <url>/api/node/{store_type}/{store_id}/{id}/rules/{rule_id}</url> or
// <url>/api/path/{store_type}/{store_id}/{id}/rules/{rule_id}</url>
// then the rule owning node ref supplied therein will be ignored,
// as these URL templates are just provided for convenience and the
// rule owning node ref is retrieved by using the rule's identifying node
// ref (supplied in {rule_id})
// create the rule's identifying node reference from the given // create the rule's identifying node reference from the given
// URL template tokens // URL template tokens
NodeRef ruleNodeRef = this.rulesHelper.getNodeRefFromWebScriptUrl(req, storeType, storeId, ruleNodeId); NodeRef ruleNodeRef = this.rulesHelper.getNodeRefFromWebScriptUrl(req, storeType, storeId, ruleNodeId);
// get the rule using it's unique identifying node reference // if ruleNodeRef referred to by {store_type} {store_id} {rule_id} is 'null' then the rule identified by that
// given node id or node path no longer exists
if (ruleNodeRef == null)
{
throw new WebScriptException(Status.STATUS_NOT_FOUND, "Rule identified by rule node/path - 'store_type': "
+ storeType + " 'store_id': " + storeId + " and 'rule_id': " + ruleNodeId + " could not be found");
}
Rule rule = this.ruleService.getRule(ruleNodeRef); Rule rule = this.ruleService.getRule(ruleNodeRef);
NodeRef ruleOwningNodeRef = this.ruleService.getOwningNodeRef(rule); NodeRef ruleOwningNodeRef = this.ruleService.getOwningNodeRef(rule);

View File

@@ -38,6 +38,16 @@ import org.alfresco.web.scripts.WebScriptRequest;
/** /**
* Web Script to GET the rule identified by the given rule node reference. * Web Script to GET the rule identified by the given rule node reference.
* *
* NOTE -
* that if a value is provided for the 'id' URL template variable {id},
* i.e. either of the following URL patterns have been used
* <url>/api/node/{store_type}/{store_id}/{id}/rules/{rule_id}</url> or
* <url>/api/path/{store_type}/{store_id}/{id}/rules/{rule_id}</url>
* then the rule owning node ref supplied therein will be ignored,
* as these URL templates are just provided for convenience and the
* rule owning node ref is retrieved by using the rule's identifying node
* ref (supplied in {rule_id})
*
* @author glen johnson at alfresco dot com * @author glen johnson at alfresco dot com
*/ */
public class RuleGet extends DeclarativeWebScript public class RuleGet extends DeclarativeWebScript
@@ -45,7 +55,7 @@ public class RuleGet extends DeclarativeWebScript
// private constants // private constants
private static final String REQ_TEMPL_VAR_STORE_TYPE = "store_type"; private static final String REQ_TEMPL_VAR_STORE_TYPE = "store_type";
private static final String REQ_TEMPL_VAR_STORE_ID = "store_id"; private static final String REQ_TEMPL_VAR_STORE_ID = "store_id";
private static final String REQ_TEMPL_VAR_RULE_NODE_ID = "id"; private static final String REQ_TEMPL_VAR_RULE_NODE_ID = "rule_id";
// model property keys // model property keys
private static final String MODEL_PROP_KEY_RULE = "rule"; private static final String MODEL_PROP_KEY_RULE = "rule";
@@ -119,12 +129,12 @@ public class RuleGet extends DeclarativeWebScript
// URL template tokens // URL template tokens
NodeRef ruleNodeRef = this.rulesHelper.getNodeRefFromWebScriptUrl(req, storeType, storeId, ruleNodeId); NodeRef ruleNodeRef = this.rulesHelper.getNodeRefFromWebScriptUrl(req, storeType, storeId, ruleNodeId);
// if ruleNodeRef referred to by {store_type} {store_id} {id} is 'null' then the rule identified by that // if ruleNodeRef referred to by {store_type} {store_id} {rule_id} is 'null' then the rule identified by that
// given node id or node path no longer exists // given node id or node path no longer exists
if (ruleNodeRef == null) if (ruleNodeRef == null)
{ {
throw new WebScriptException(Status.STATUS_NOT_FOUND, "Rule identified by rule node/path - 'store_type': " throw new WebScriptException(Status.STATUS_NOT_FOUND, "Rule identified by rule node/path - 'store_type': "
+ storeType + " 'store_id': " + storeId + " and 'id': " + ruleNodeId + " could not be found"); + storeType + " 'store_id': " + storeId + " and 'rule_id': " + ruleNodeId + " could not be found");
} }
// get rule identified by the given rule node reference // get rule identified by the given rule node reference
@@ -135,7 +145,7 @@ public class RuleGet extends DeclarativeWebScript
// add objects to model for the template to render // add objects to model for the template to render
model.put(MODEL_PROP_KEY_RULE, rule); model.put(MODEL_PROP_KEY_RULE, rule);
model.put(MODEL_PROP_KEY_OWNING_NODE_REF, ruleOwningNodeRef); model.put(MODEL_PROP_KEY_OWNING_NODE_REF, ruleOwningNodeRef.toString());
return model; return model;
} }

View File

@@ -39,6 +39,16 @@ import org.json.JSONObject;
/** /**
* Web Script to PUT (update) the rule identified by the given rule node reference. * Web Script to PUT (update) the rule identified by the given rule node reference.
* *
* NOTE -
* that if a value is provided for the 'id' URL template variable {id},
* i.e. either of the following URL patterns have been used
* <url>/api/node/{store_type}/{store_id}/{id}/rules/{rule_id}</url> or
* <url>/api/path/{store_type}/{store_id}/{id}/rules/{rule_id}</url>
* then the rule owning node ref supplied therein will be ignored,
* as these URL templates are just provided for convenience and the
* rule owning node ref is retrieved by using the rule's identifying node
* ref (supplied in {rule_id})
*
* @author glen johnson at alfresco dot com * @author glen johnson at alfresco dot com
*/ */
public class RulePut extends DeclarativeWebScript public class RulePut extends DeclarativeWebScript
@@ -46,10 +56,11 @@ public class RulePut extends DeclarativeWebScript
// private constants // private constants
private static final String REQ_TEMPL_VAR_STORE_TYPE = "store_type"; private static final String REQ_TEMPL_VAR_STORE_TYPE = "store_type";
private static final String REQ_TEMPL_VAR_STORE_ID = "store_id"; private static final String REQ_TEMPL_VAR_STORE_ID = "store_id";
private static final String REQ_TEMPL_VAR_RULE_NODE_ID = "id"; private static final String REQ_TEMPL_VAR_RULE_NODE_ID = "rule_id";
// model property keys // model property keys
private static final String MODEL_PROP_KEY_RULE = "rule"; private static final String MODEL_PROP_KEY_RULE = "rule";
private static final String MODEL_PROP_KEY_OWNING_NODE_REF = "owningNodeRef";
// properties for services // properties for services
private RuleService ruleService; private RuleService ruleService;
@@ -120,6 +131,14 @@ public class RulePut extends DeclarativeWebScript
// URL template tokens // URL template tokens
NodeRef ruleNodeRef = this.rulesHelper.getNodeRefFromWebScriptUrl(req, storeType, storeId, ruleNodeId); NodeRef ruleNodeRef = this.rulesHelper.getNodeRefFromWebScriptUrl(req, storeType, storeId, ruleNodeId);
// if ruleNodeRef referred to by {store_type} {store_id} {rule_id} is 'null' then the rule identified by that
// given node id or node path no longer exists
if (ruleNodeRef == null)
{
throw new WebScriptException(Status.STATUS_NOT_FOUND, "Rule identified by rule node/path - 'store_type': "
+ storeType + " 'store_id': " + storeId + " and 'rule_id': " + ruleNodeId + " could not be found");
}
// get the rule JSON object sent in the request content (when PUTting the Rule) // get the rule JSON object sent in the request content (when PUTting the Rule)
Object contentObj = req.parseContent(); Object contentObj = req.parseContent();
if (contentObj == null || !(contentObj instanceof JSONObject)) if (contentObj == null || !(contentObj instanceof JSONObject))
@@ -129,19 +148,20 @@ public class RulePut extends DeclarativeWebScript
} }
JSONObject ruleJson = (JSONObject)contentObj; JSONObject ruleJson = (JSONObject)contentObj;
// get the rule object (identified by the rule node reference) // update the rule object identified by the given rule node reference
// updated by the details in the rule JSON object // with the details in the rule JSON
Rule rule = this.rulesHelper.getRuleFromJson(ruleJson, ruleNodeRef); Rule rule = this.rulesHelper.getRuleFromJson(ruleJson, ruleNodeRef);
// get owning node ref that rule was // get owning node ref that rule was
// previous applied to // previous applied to
NodeRef owningNodeRef = this.ruleService.getOwningNodeRef(rule); NodeRef ruleOwningNodeRef = this.ruleService.getOwningNodeRef(rule);
// re-apply rule to actionable node // re-apply rule to owning node
this.ruleService.saveRule(owningNodeRef, rule); this.ruleService.saveRule(ruleOwningNodeRef, rule);
// add objects to model for the template to render // add objects to model for the template to render
model.put(MODEL_PROP_KEY_RULE, rule); model.put(MODEL_PROP_KEY_RULE, rule);
model.put(MODEL_PROP_KEY_OWNING_NODE_REF, ruleOwningNodeRef.toString());
return model; return model;
} }

View File

@@ -25,9 +25,11 @@
package org.alfresco.repo.web.scripts.rule; package org.alfresco.repo.web.scripts.rule;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.evaluator.CompareMimeTypeEvaluator;
import org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator; import org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator;
import org.alfresco.repo.action.executer.CompositeActionExecuter; import org.alfresco.repo.action.executer.CompositeActionExecuter;
import org.alfresco.repo.action.executer.CopyActionExecuter; import org.alfresco.repo.action.executer.CopyActionExecuter;
@@ -36,7 +38,6 @@ import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.web.scripts.BaseWebScriptTest; import org.alfresco.repo.web.scripts.BaseWebScriptTest;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.rule.RuleType; import org.alfresco.service.cmr.rule.RuleType;
@@ -49,6 +50,7 @@ import org.alfresco.web.scripts.Status;
import org.alfresco.web.scripts.TestWebScriptServer.DeleteRequest; import org.alfresco.web.scripts.TestWebScriptServer.DeleteRequest;
import org.alfresco.web.scripts.TestWebScriptServer.GetRequest; import org.alfresco.web.scripts.TestWebScriptServer.GetRequest;
import org.alfresco.web.scripts.TestWebScriptServer.PostRequest; import org.alfresco.web.scripts.TestWebScriptServer.PostRequest;
import org.alfresco.web.scripts.TestWebScriptServer.PutRequest;
import org.alfresco.web.scripts.TestWebScriptServer.Response; import org.alfresco.web.scripts.TestWebScriptServer.Response;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
@@ -65,16 +67,17 @@ public class RuleServiceTest extends BaseWebScriptTest
private AuthenticationComponent authenticationComponent; private AuthenticationComponent authenticationComponent;
private NodeService nodeService; private NodeService nodeService;
private PersonService personService; private PersonService personService;
private ActionService actionService;
private NodeRef owningNodeRef1; private NodeRef owningNodeRef1;
private NodeRef testDestFolder1; private NodeRef testDestFolder1;
private NodeRef testDestFolder2;
// private constants // private constants
private static final String RULES_USER = "Rules.User"; private static final String RULES_USER = "Rules.User";
private static final String RULES_USER_PASSWORD = "password"; private static final String RULES_USER_PASSWORD = "password";
private static final String RULES_TEST_OWNING_FOLDER_1 = "rulesTestOwningFolder1"; private static final String RULES_TEST_OWNING_FOLDER_1 = "rulesTestOwningFolder1";
private static final String RULES_TEST_DEST_FOLDER_1 = "rulesTestDestinationFolder1"; private static final String RULES_TEST_DEST_FOLDER_1 = "rulesTestDestinationFolder1";
private static final String RULES_TEST_DEST_FOLDER_2 = "rulesTestDestinationFolder2";
@Override @Override
protected void setUp() throws Exception protected void setUp() throws Exception
@@ -88,7 +91,6 @@ public class RuleServiceTest extends BaseWebScriptTest
"AuthenticationComponent"); "AuthenticationComponent");
this.nodeService = (NodeService) getServer().getApplicationContext().getBean("NodeService"); this.nodeService = (NodeService) getServer().getApplicationContext().getBean("NodeService");
this.personService = (PersonService) getServer().getApplicationContext().getBean("PersonService"); this.personService = (PersonService) getServer().getApplicationContext().getBean("PersonService");
this.actionService = (ActionService) getServer().getApplicationContext().getBean("ActionService");
// //
// various setup operations which need to be run as system user // various setup operations which need to be run as system user
@@ -117,6 +119,9 @@ public class RuleServiceTest extends BaseWebScriptTest
this.testDestFolder1 = this.nodeService.createNode(userHomeRef, ContentModel.ASSOC_CONTAINS, this.testDestFolder1 = this.nodeService.createNode(userHomeRef, ContentModel.ASSOC_CONTAINS,
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, RULES_TEST_DEST_FOLDER_1), QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, RULES_TEST_DEST_FOLDER_1),
ContentModel.TYPE_FOLDER).getChildRef(); ContentModel.TYPE_FOLDER).getChildRef();
this.testDestFolder2 = this.nodeService.createNode(userHomeRef, ContentModel.ASSOC_CONTAINS,
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, RULES_TEST_DEST_FOLDER_2),
ContentModel.TYPE_FOLDER).getChildRef();
} }
@Override @Override
@@ -345,8 +350,14 @@ public class RuleServiceTest extends BaseWebScriptTest
// Construct rule JSON object // Construct rule JSON object
JSONObject rule = new JSONObject(); JSONObject rule = new JSONObject();
rule.put("owningNodeRef", owningNodeRef); if (owningNodeRef != null)
rule.put("ruleNodeRef", ruleNodeRef); {
rule.put("owningNodeRef", owningNodeRef.toString());
}
if (ruleNodeRef != null)
{
rule.put("ruleNodeRef", ruleNodeRef.toString());
}
rule.put("title", title); rule.put("title", title);
rule.put("description", description); rule.put("description", description);
rule.put("ruleTypes", new JSONArray(ruleTypes)); rule.put("ruleTypes", new JSONArray(ruleTypes));
@@ -421,9 +432,9 @@ public class RuleServiceTest extends BaseWebScriptTest
// create nested action parameters // create nested action parameters
JSONObject actionCopyParamsJson = new JSONObject(); JSONObject actionCopyParamsJson = new JSONObject();
actionCopyParamsJson.put(MoveActionExecuter.PARAM_ASSOC_QNAME, actionCopyParamsJson.put(MoveActionExecuter.PARAM_ASSOC_QNAME,
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "copy")); QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "copy").toString());
actionCopyParamsJson.put(MoveActionExecuter.PARAM_DESTINATION_FOLDER, this.testDestFolder1); actionCopyParamsJson.put(MoveActionExecuter.PARAM_DESTINATION_FOLDER, this.testDestFolder1.toString());
actionCopyParamsJson.put(MoveActionExecuter.PARAM_ASSOC_TYPE_QNAME, ContentModel.ASSOC_CONTAINS); actionCopyParamsJson.put(MoveActionExecuter.PARAM_ASSOC_TYPE_QNAME, ContentModel.ASSOC_CONTAINS.toString());
// create nested actions // create nested actions
JSONObject actionCopyJson = getActionJsonObject(null, CopyActionExecuter.NAME, "CopyTitle", "CopyDesc", false, JSONObject actionCopyJson = getActionJsonObject(null, CopyActionExecuter.NAME, "CopyTitle", "CopyDesc", false,
@@ -485,9 +496,9 @@ public class RuleServiceTest extends BaseWebScriptTest
// create nested action parameters // create nested action parameters
JSONObject actionCopyParamsJson = new JSONObject(); JSONObject actionCopyParamsJson = new JSONObject();
actionCopyParamsJson.put(MoveActionExecuter.PARAM_ASSOC_QNAME, actionCopyParamsJson.put(MoveActionExecuter.PARAM_ASSOC_QNAME,
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "copy")); QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "copy").toString());
actionCopyParamsJson.put(MoveActionExecuter.PARAM_DESTINATION_FOLDER, this.testDestFolder1); actionCopyParamsJson.put(MoveActionExecuter.PARAM_DESTINATION_FOLDER, this.testDestFolder1.toString());
actionCopyParamsJson.put(MoveActionExecuter.PARAM_ASSOC_TYPE_QNAME, ContentModel.ASSOC_CONTAINS); actionCopyParamsJson.put(MoveActionExecuter.PARAM_ASSOC_TYPE_QNAME, ContentModel.ASSOC_CONTAINS.toString());
// create nested action // create nested action
JSONObject actionCopyJson = getActionJsonObject(null, CopyActionExecuter.NAME, "CopyTitle", "CopyDesc", false, JSONObject actionCopyJson = getActionJsonObject(null, CopyActionExecuter.NAME, "CopyTitle", "CopyDesc", false,
@@ -527,6 +538,7 @@ public class RuleServiceTest extends BaseWebScriptTest
sendRequest(new GetRequest(url), Status.STATUS_NOT_FOUND); sendRequest(new GetRequest(url), Status.STATUS_NOT_FOUND);
} }
@SuppressWarnings("unchecked")
public void testGetRule() throws Exception public void testGetRule() throws Exception
{ {
// //
@@ -538,7 +550,7 @@ public class RuleServiceTest extends BaseWebScriptTest
JSONObject condCompMimeTypeParams = new JSONObject(); JSONObject condCompMimeTypeParams = new JSONObject();
condCompMimeTypeParams.put(ComparePropertyValueEvaluator.PARAM_VALUE, "image/png"); condCompMimeTypeParams.put(ComparePropertyValueEvaluator.PARAM_VALUE, "image/png");
// create conditions // create conditions JSON array
JSONObject conditionCompMimeType = getConditionJsonObject(null, condCompMimeTypeParams, "compare-mime-type", false, null); JSONObject conditionCompMimeType = getConditionJsonObject(null, condCompMimeTypeParams, "compare-mime-type", false, null);
JSONArray conditions = new JSONArray(); JSONArray conditions = new JSONArray();
conditions.put(conditionCompMimeType); conditions.put(conditionCompMimeType);
@@ -546,9 +558,9 @@ public class RuleServiceTest extends BaseWebScriptTest
// create parameters for nested actions // create parameters for nested actions
JSONObject actionCopyParamsJson = new JSONObject(); JSONObject actionCopyParamsJson = new JSONObject();
actionCopyParamsJson.put(MoveActionExecuter.PARAM_ASSOC_QNAME, actionCopyParamsJson.put(MoveActionExecuter.PARAM_ASSOC_QNAME,
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "copy")); QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "copy").toString());
actionCopyParamsJson.put(MoveActionExecuter.PARAM_DESTINATION_FOLDER, this.testDestFolder1); actionCopyParamsJson.put(MoveActionExecuter.PARAM_DESTINATION_FOLDER, this.testDestFolder1.toString());
actionCopyParamsJson.put(MoveActionExecuter.PARAM_ASSOC_TYPE_QNAME, ContentModel.ASSOC_CONTAINS); actionCopyParamsJson.put(MoveActionExecuter.PARAM_ASSOC_TYPE_QNAME, ContentModel.ASSOC_CONTAINS.toString());
// create nested actions // create nested actions
JSONObject actionCopyJson = getActionJsonObject(null, CopyActionExecuter.NAME, "CopyTitle", "CopyDesc", false, JSONObject actionCopyJson = getActionJsonObject(null, CopyActionExecuter.NAME, "CopyTitle", "CopyDesc", false,
@@ -556,15 +568,15 @@ public class RuleServiceTest extends BaseWebScriptTest
JSONArray nestedActions = new JSONArray(); JSONArray nestedActions = new JSONArray();
nestedActions.put(actionCopyJson); nestedActions.put(actionCopyJson);
// create rule's composite action // create rule's root action
JSONObject compoActionJson = getActionJsonObject(null, CompositeActionExecuter.NAME, "Rule1Action", "Rule1ActionDesc", JSONObject ruleActionJson = getActionJsonObject(null, CompositeActionExecuter.NAME, "Rule1Action", "Rule1ActionDesc",
false, null, conditions, nestedActions, null, null); false, null, conditions, nestedActions, null, null);
// create rule to POST // create rule JSON
List<String> ruleTypes = new ArrayList<String>(); List<String> ruleTypes = new ArrayList<String>();
ruleTypes.add(RuleType.UPDATE); ruleTypes.add(RuleType.UPDATE);
JSONObject ruleJson = getRuleJsonObject(this.owningNodeRef1, null, "Rule1", "Rule1Desc", ruleTypes, JSONObject ruleJson = getRuleJsonObject(null, null, "Rule1", "Rule1Desc", ruleTypes,
compoActionJson, false, false, false, null); ruleActionJson, false, false, false, null);
// POST rule JSON to rules collection resource // POST rule JSON to rules collection resource
JSONObject resultPostRule = postRules(this.owningNodeRef1, ruleJson); JSONObject resultPostRule = postRules(this.owningNodeRef1, ruleJson);
@@ -583,9 +595,106 @@ public class RuleServiceTest extends BaseWebScriptTest
Response response = sendRequest(new GetRequest(getRuleRulesBasedUrl), Status.STATUS_OK); Response response = sendRequest(new GetRequest(getRuleRulesBasedUrl), Status.STATUS_OK);
JSONObject resultGetRule = new JSONObject(response.getContentAsString()); JSONObject resultGetRule = new JSONObject(response.getContentAsString());
String resultRuleNodeRefStr = resultGetRule.getString("ruleNodeRef"); //
// validate properties returned in GET Rule response
//
assertEquals(ruleNodeRefStr, resultRuleNodeRefStr); //
// check rule properties
//
assertEquals(this.owningNodeRef1.toString(), resultGetRule.getString("owningNodeRef"));
assertEquals(ruleNodeRefStr, resultGetRule.getString("ruleNodeRef"));
assertEquals("Rule1", resultGetRule.getString("title"));
assertEquals("Rule1Desc", resultGetRule.getString("description"));
assertEquals(false, resultGetRule.getBoolean("executeAsync"));
assertEquals(false, resultGetRule.getBoolean("ruleDisabled"));
assertEquals(false, resultGetRule.getBoolean("appliedToChildren"));
//
// check rule types
//
JSONArray resultRuleTypes = resultGetRule.getJSONArray("ruleTypes");
assertEquals(1, resultRuleTypes.length());
assertEquals(RuleType.UPDATE, resultRuleTypes.getString(0));
// retrieve ID for copy action
JSONObject resultRuleAction = resultGetRule.getJSONObject("action");
JSONObject resultNestedActions = resultRuleAction.getJSONObject("actions");
Iterator<String> actionKeysIter = resultNestedActions.keys();
String resultCopyActionID = null;
while (actionKeysIter.hasNext())
{
String key = actionKeysIter.next();
JSONObject resultAction = resultNestedActions.getJSONObject(key);
String actionDefName = resultAction.getString("actionDefinitionName");
if (actionDefName.equals(CopyActionExecuter.NAME))
{
resultCopyActionID = resultAction.getString("id");
break;
}
}
assertNotNull(resultCopyActionID);
// retrieve copy action
JSONObject resCopyAction = resultNestedActions.getJSONObject(resultCopyActionID);
//
// check copy action properties
//
assertEquals(CopyActionExecuter.NAME, resCopyAction.getString("actionDefinitionName"));
assertEquals("CopyTitle", resCopyAction.getString("title"));
assertEquals("CopyDesc" , resCopyAction.getString("description"));
assertEquals(false, resCopyAction.getBoolean("executeAsync"));
//
// check copy action parameters
//
JSONObject resCopyActionParams = resCopyAction.getJSONObject("parameterValues");
assertEquals(QName.createQName(
NamespaceService.CONTENT_MODEL_1_0_URI, "copy").toString(),
resCopyActionParams.getString(MoveActionExecuter.PARAM_ASSOC_QNAME));
assertEquals(this.testDestFolder1.toString(), resCopyActionParams.getString(MoveActionExecuter.PARAM_DESTINATION_FOLDER));
assertEquals(ContentModel.ASSOC_CONTAINS.toString(), resCopyActionParams.getString(MoveActionExecuter.PARAM_ASSOC_TYPE_QNAME));
// retrieve ID for compare MIME-type condition
JSONObject resultConditions = resultRuleAction.getJSONObject("conditions");
Iterator<String> condKeysIter = resultConditions.keys();
String resultCondCompMimeTypeID = null;
while (condKeysIter.hasNext())
{
String key = condKeysIter.next();
JSONObject resultCondition = resultConditions.getJSONObject(key);
String condDefName = resultCondition.getString("conditionDefinitionName");
if (condDefName.equals(CompareMimeTypeEvaluator.NAME))
{
resultCondCompMimeTypeID = resultCondition.getString("id");
break;
}
}
assertNotNull(resultCondCompMimeTypeID);
//
// retrieve compare MIME-type condition
//
JSONObject resCompMimeTypeCond = resultConditions.getJSONObject(resultCondCompMimeTypeID);
//
// check compare MIME type condition's properties
//
assertEquals(CompareMimeTypeEvaluator.NAME, resCompMimeTypeCond.getString("conditionDefinitionName"));
assertEquals(false, resCompMimeTypeCond.getBoolean("invertCondition"));
//
// retrieve compare MIME-type condition's parameter JSON and check its value
//
JSONObject resCondCmpMimeTypeParams = resCompMimeTypeCond.getJSONObject("parameterValues");
assertEquals("image/png", resCondCmpMimeTypeParams.getString(ComparePropertyValueEvaluator.PARAM_VALUE));
} }
public void testGetRules() throws Exception public void testGetRules() throws Exception
@@ -606,9 +715,9 @@ public class RuleServiceTest extends BaseWebScriptTest
// create parameters for nested actions // create parameters for nested actions
JSONObject actionCopyParamsJson = new JSONObject(); JSONObject actionCopyParamsJson = new JSONObject();
actionCopyParamsJson.put(MoveActionExecuter.PARAM_ASSOC_QNAME, actionCopyParamsJson.put(MoveActionExecuter.PARAM_ASSOC_QNAME,
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "copy")); QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "copy").toString());
actionCopyParamsJson.put(MoveActionExecuter.PARAM_DESTINATION_FOLDER, this.testDestFolder1); actionCopyParamsJson.put(MoveActionExecuter.PARAM_DESTINATION_FOLDER, this.testDestFolder1.toString());
actionCopyParamsJson.put(MoveActionExecuter.PARAM_ASSOC_TYPE_QNAME, ContentModel.ASSOC_CONTAINS); actionCopyParamsJson.put(MoveActionExecuter.PARAM_ASSOC_TYPE_QNAME, ContentModel.ASSOC_CONTAINS.toString());
// create nested actions // create nested actions
JSONObject actionCopyJson = getActionJsonObject(null, CopyActionExecuter.NAME, "CopyTitle", "CopyDesc", false, JSONObject actionCopyJson = getActionJsonObject(null, CopyActionExecuter.NAME, "CopyTitle", "CopyDesc", false,
@@ -650,8 +759,234 @@ public class RuleServiceTest extends BaseWebScriptTest
assertTrue(postedRuleFound == true); assertTrue(postedRuleFound == true);
} }
public void testPostRules() @SuppressWarnings("unchecked")
throws Exception public void testPutRule() throws Exception
{
// -------------------------
// Create a Rule - POST Rule
// -------------------------
// create condition parameters
JSONObject condCompMimeTypeParams = new JSONObject();
condCompMimeTypeParams.put(ComparePropertyValueEvaluator.PARAM_VALUE, "image/png");
//
// create conditions JSON
//
JSONObject conditionCompMimeType = getConditionJsonObject(null, condCompMimeTypeParams, "compare-mime-type", false, null);
JSONArray conditions = new JSONArray();
conditions.put(conditionCompMimeType);
//
// create parameters for nested actions JSON
//
JSONObject actionCopyParamsJson = new JSONObject();
actionCopyParamsJson.put(MoveActionExecuter.PARAM_ASSOC_QNAME,
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "copy").toString());
actionCopyParamsJson.put(MoveActionExecuter.PARAM_DESTINATION_FOLDER, this.testDestFolder1.toString());
actionCopyParamsJson.put(MoveActionExecuter.PARAM_ASSOC_TYPE_QNAME, ContentModel.ASSOC_CONTAINS.toString());
//
// create nested actions JSON
//
JSONObject actionCopyJson = getActionJsonObject(null, CopyActionExecuter.NAME, "CopyTitle", "CopyDesc", false,
actionCopyParamsJson, null, null, null, null);
JSONArray nestedActions = new JSONArray();
nestedActions.put(actionCopyJson);
//
// create rule's composite action JSON
//
JSONObject compoActionJson = getActionJsonObject(null, CompositeActionExecuter.NAME, "Rule1Action", "Rule1ActionDesc",
false, null, conditions, nestedActions, null, null);
//
// create rule to POST JSON
//
List<String> ruleTypes = new ArrayList<String>();
ruleTypes.add(RuleType.UPDATE);
JSONObject ruleJson = getRuleJsonObject(this.owningNodeRef1, null, "Rule", "RuleDesc", ruleTypes,
compoActionJson, false, false, false, null);
//
// POST rule JSON to rules collection resource JSON
//
JSONObject resultRuleJson = postRules(this.owningNodeRef1, ruleJson);
// get the rule node ref from the rule details returned so that
// we can retrieve the rule later
String ruleNodeRefStr = resultRuleJson.getString("ruleNodeRef");
NodeRef ruleNodeRef = new NodeRef(ruleNodeRefStr);
// --------------------------
// Update the Rule - PUT Rule
// --------------------------
// create parameter for compare MIME-type condition with updated parameter value
JSONObject putCondCompMimeTypeParams = new JSONObject();
putCondCompMimeTypeParams.put(ComparePropertyValueEvaluator.PARAM_VALUE, "image/jpeg");
// retrieve ID for compare MIME-type condition
JSONObject resultRuleAction = resultRuleJson.getJSONObject("action");
JSONObject resultConditions = resultRuleAction.getJSONObject("conditions");
Iterator<String> condKeysIter = resultConditions.keys();
String resultCondCompMimeTypeID = null;
while (condKeysIter.hasNext())
{
String key = condKeysIter.next();
JSONObject resultCondition = resultConditions.getJSONObject(key);
String condDefName = resultCondition.getString("conditionDefinitionName");
if (condDefName.equals("compare-mime-type"))
{
resultCondCompMimeTypeID = resultCondition.getString("id");
break;
}
}
assertNotNull(resultCondCompMimeTypeID);
// create compare MIME-type condition with updated condition parameters and updated properties
JSONObject putConditionCompMimeType = new JSONObject();
putConditionCompMimeType.put("id", resultCondCompMimeTypeID);
putConditionCompMimeType.put("parameterValues", putCondCompMimeTypeParams);
putConditionCompMimeType.put("conditionDefinitionName", "compare-mime-type");
putConditionCompMimeType.put("invertCondition", true);
// create conditions JSON array and add updated compare MIME-type condition
JSONArray putConditions = new JSONArray();
putConditions.put(putConditionCompMimeType);
// create parameters for copy action JSON with updated parameter values
JSONObject putCopyActionParams = new JSONObject();
putCopyActionParams.put(MoveActionExecuter.PARAM_DESTINATION_FOLDER, this.testDestFolder2.toString());
// retrieve ID for copy action
JSONObject resultActions = resultRuleAction.getJSONObject("actions");
Iterator<String> actionKeysIter = resultActions.keys();
String resultCopyActionID = null;
while (actionKeysIter.hasNext())
{
String key = actionKeysIter.next();
JSONObject resultAction = resultActions.getJSONObject(key);
String actionDefName = resultAction.getString("actionDefinitionName");
if (actionDefName.equals(CopyActionExecuter.NAME))
{
resultCopyActionID = resultAction.getString("id");
break;
}
}
assertNotNull(resultCopyActionID);
// create copy action with updated action parameters and updated properties
JSONObject putCopyAction = new JSONObject();
putCopyAction.put("id", resultCopyActionID);
putCopyAction.put("actionDefinitionName", CopyActionExecuter.NAME);
putCopyAction.put("title", "CopyTitleUpdated");
putCopyAction.put("description", "CopyDescUpdated");
putCopyAction.put("executeAsync", true);
putCopyAction.put("parameterValues", putCopyActionParams);
// create nested actions JSON array and add updated copy action
JSONArray putNestedActions = new JSONArray();
putNestedActions.put(putCopyAction);
// create rule action JSON (root action) with updated properties, conditions and nested actions
JSONObject putRuleAction = new JSONObject();
putRuleAction.put("id", resultRuleAction.getString("id"));
putRuleAction.put("actionDefinitionName", CompositeActionExecuter.NAME);
putRuleAction.put("actions", putNestedActions);
putRuleAction.put("conditions", putConditions);
// create updated rule types JSON array
JSONArray putRuleTypes = new JSONArray();
putRuleTypes.put(RuleType.INBOUND);
// create rule JSON with updated composite action, updated rule types and updated rule properties
JSONObject putRuleJson = new JSONObject();
putRuleJson.put("title", "RuleTitleUpdated");
putRuleJson.put("description", "RuleDescUpdated");
putRuleJson.put("ruleTypes", putRuleTypes);
putRuleJson.put("action", putRuleAction);
putRuleJson.put("executeAsync", true);
putRuleJson.put("ruleDisabled", true);
//
// update rule resource with updated rule JSON with PUT Rule
//
String url = "/api/rules/" + ruleNodeRef.getStoreRef().getProtocol() + "/"
+ ruleNodeRef.getStoreRef().getIdentifier() + "/" + ruleNodeRef.getId();
sendRequest(new PutRequest(url, putRuleJson.toString(), "application/json"),
Status.STATUS_OK);
// -----------------------------------------------
// Get the updated Rule - GET Rule
// and validate that the response thereof contains
// the updated field values
// -----------------------------------------------
//
// get the updated rule
//
Response responseGetRule = sendRequest(new GetRequest(url), Status.STATUS_OK);
JSONObject resGetRule = new JSONObject(responseGetRule.getContentAsString());
//
// check updated rule fields
//
assertEquals("RuleTitleUpdated", resGetRule.getString("title"));
assertEquals("RuleDescUpdated", resGetRule.getString("description"));
assertEquals(true, resGetRule.getBoolean("executeAsync"));
assertEquals(true, resGetRule.getBoolean("ruleDisabled"));
//
// retrieve updated copy action
//
JSONObject resRuleAction = resGetRule.getJSONObject("action");
JSONObject resNestedActions = resRuleAction.getJSONObject("actions");
String copyActionId = putCopyAction.getString("id");
JSONObject resCopyAction = resNestedActions.getJSONObject(copyActionId);
//
// check updated copy action fields
//
assertEquals(CopyActionExecuter.NAME, resCopyAction.getString("actionDefinitionName"));
assertEquals("CopyTitleUpdated", resCopyAction.getString("title"));
assertEquals("CopyDescUpdated" , resCopyAction.getString("description"));
assertEquals(true, resCopyAction.getBoolean("executeAsync"));
//
// check updated copy action parameters
//
JSONObject resCopyActionParams = resCopyAction.getJSONObject("parameterValues");
assertEquals(this.testDestFolder2.toString(), resCopyActionParams.getString(MoveActionExecuter.PARAM_DESTINATION_FOLDER));
//
// retrieve updated compare MIME-type condition
//
JSONObject resConditions = resRuleAction.getJSONObject("conditions");
String compMimeTypeCondId = putConditionCompMimeType.getString("id");
JSONObject resCompMimeTypeCond = resConditions.getJSONObject(compMimeTypeCondId);
//
// check updated compare MIME type condition's fields
//
assertEquals(true, resCompMimeTypeCond.getBoolean("invertCondition"));
//
// retrieve compare MIME-type condition's parameter JSON and check its value
//
JSONObject resCondCmpMimeTypeParams = resCompMimeTypeCond.getJSONObject("parameterValues");
assertEquals("image/jpeg", resCondCmpMimeTypeParams.getString(ComparePropertyValueEvaluator.PARAM_VALUE));
}
public void testPostRules() throws Exception
{ {
// create condition parameters for compare MIME type condition // create condition parameters for compare MIME type condition
JSONObject condCompMimeTypeParams = new JSONObject(); JSONObject condCompMimeTypeParams = new JSONObject();
@@ -692,8 +1027,6 @@ public class RuleServiceTest extends BaseWebScriptTest
// validate rule result // validate rule result
// //
NodeRef resultRuleNodeRef = new NodeRef(resultRule.getString("ruleNodeRef"));
assertEquals(this.owningNodeRef1.toString(), resultRule.getString("owningNodeRef")); assertEquals(this.owningNodeRef1.toString(), resultRule.getString("owningNodeRef"));
assertEquals("Rule1", resultRule.getString("title")); assertEquals("Rule1", resultRule.getString("title"));
assertEquals("Rule1Desc", resultRule.getString("description")); assertEquals("Rule1Desc", resultRule.getString("description"));
@@ -800,8 +1133,6 @@ public class RuleServiceTest extends BaseWebScriptTest
JSONArray result = new JSONArray(response.getContentAsString()); JSONArray result = new JSONArray(response.getContentAsString());
assertTrue(result.length() > 0); assertTrue(result.length() > 0);
System.out.println(result);
} }
public void testGetConditionDef() throws Exception public void testGetConditionDef() throws Exception

View File

@@ -155,7 +155,7 @@ public class RulesGet extends DeclarativeWebScript
// add objects to model for the template to render // add objects to model for the template to render
model.put(MODEL_PROP_KEY_RULES, rules); model.put(MODEL_PROP_KEY_RULES, rules);
model.put(MODEL_PROP_KEY_OWNING_NODE_REF, owningNodeRef); model.put(MODEL_PROP_KEY_OWNING_NODE_REF, owningNodeRef.toString());
return model; return model;
} }

View File

@@ -171,62 +171,83 @@ public class RulesHelper
rule = new Rule(); rule = new Rule();
} }
//
// set rule properties
//
try try
{ {
//
// set rule properties
//
if ((ruleJson.isNull("title") == true) && (update == false)) if ((ruleJson.isNull("title") == true) && (update == false))
{ {
// the "title" field is mandatory, it is missing in the rule details, // the "title" field is missing in the rule details,
// and we are creating a new rule, so throw an exception // and we are creating a new rule,
// but the "title" field is mandatory, so throw an exception
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "A new rule is being created but the 'title' " throw new WebScriptException(Status.STATUS_BAD_REQUEST, "A new rule is being created but the 'title' "
+ "field, which is mandatory, has not been included in the rule details"); + "field, which is mandatory, has not been included in the rule details");
} }
// otherwise go ahead and set the value if the field is present // otherwise just go ahead and set the value if the field is present
// to over both creating and updating scenarios
else if (ruleJson.isNull("title") == false) else if (ruleJson.isNull("title") == false)
{ {
String ruleTitle = ruleJson.getString("title"); String ruleTitle = ruleJson.getString("title");
rule.setTitle(ruleTitle); rule.setTitle(ruleTitle);
} }
}
catch (JSONException je)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "There was a problem reading the 'title' property "
+ "in the received Rule JSON. It may contain invalid characters", je);
}
try
{
if (ruleJson.isNull("description") == false) if (ruleJson.isNull("description") == false)
{ {
rule.setDescription(ruleJson.getString("description")); rule.setDescription(ruleJson.getString("description"));
} }
}
catch (JSONException je)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "There was a problem reading the 'description' property "
+ "in the received Rule JSON. It may contain invalid characters. The title of the offending rule is '"
+ ruleJson.optString("title") + "'", je);
}
// set values from the respective Boolean fields below, but if the
// if the value given for a field does not equate to either
// 'true' or 'false', then set it to a default value of false
if (ruleJson.isNull("executeAsync") == false)
{
rule.setExecuteAsynchronously(ruleJson.optBoolean("executeAsync", false));
}
if (ruleJson.isNull("ruleDisabled") == false)
{
rule.setRuleDisabled(ruleJson.optBoolean("ruleDisabled", false));
}
// set values from the respective Boolean fields below, but if the
// if the value given for a field does not equate to either if (ruleJson.isNull("appliedToChildren") == false)
// 'true' or 'false', then set it to a default value of false {
rule.applyToChildren(ruleJson.optBoolean("appliedToChildren", false));
if (ruleJson.isNull("executeAsync") == false) }
{
rule.setExecuteAsynchronously(ruleJson.optBoolean("executeAsync", false)); //
} // set rule types present in the rule details onto the rule
//
if (ruleJson.isNull("ruleDisabled") == false) try
{ {
rule.setRuleDisabled(ruleJson.optBoolean("ruleDisabled", false));
}
if (ruleJson.isNull("appliedToChildren") == false)
{
rule.applyToChildren(ruleJson.optBoolean("appliedToChildren", false));
}
//
// set rule types present in the rule details onto the rule
//
if ((ruleJson.isNull("ruleTypes") == true) && (update == false)) if ((ruleJson.isNull("ruleTypes") == true) && (update == false))
{ {
// the "ruleTypes" field is mandatory, it is missing in the rule details, // the "ruleTypes" field is mandatory for rule creation. it is missing in the rule details
// and we are creating a new rule so throw an exception // from which we are creating a new rule, so throw an exception
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "A new rule is being created but the 'ruleTypes' " throw new WebScriptException(Status.STATUS_BAD_REQUEST, "A new rule is being created but the 'ruleTypes' "
+ "field, which is mandatory, has not been included in the rule details"); + "property, which is mandatory, has not been included in the rule details. The title of the "
+ "offending rule is '" + ruleJson.optString("title") + "'");
} }
else if (ruleJson.isNull("ruleTypes") == false) else if (ruleJson.isNull("ruleTypes") == false)
{ {
@@ -238,7 +259,8 @@ public class RulesHelper
if (numRuleTypes < 1) if (numRuleTypes < 1)
{ {
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "At least one rule type needs to be present in " throw new WebScriptException(Status.STATUS_BAD_REQUEST, "At least one rule type needs to be present in "
+ "in the rule details sent in the request content."); + "in the rule details sent in the request content. The title of the "
+ "offending rule is '" + ruleJson.optString("title") + "'");
} }
// add to the rule the rule type names sent in the rule details // add to the rule the rule type names sent in the rule details
@@ -253,57 +275,83 @@ public class RulesHelper
{ {
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "An invalid rule type name was given in the " throw new WebScriptException(Status.STATUS_BAD_REQUEST, "An invalid rule type name was given in the "
+ "rule details sent in the request content. Invalid rule type name given is: '" + "rule details sent in the request content. Invalid rule type name given is: '"
+ ruleTypeNameJson + "'"); + ruleTypeNameJson + "'. The title of the offending rule containing the invalid rule type "
+ "is '" + ruleJson.optString("title") + "'");
} }
} }
rule.setRuleTypes(ruleTypes); rule.setRuleTypes(ruleTypes);
} }
if ((ruleJson.isNull("action") == true) && (update == false))
{
// the "action" field is mandatory, it is missing in the rule details,
// and we are creating a new rule so throw an exception
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "A new rule is being created but the 'action' "
+ "field, which is mandatory, has not been included in the rule details");
}
else
{
// set the action supplied in the rule details onto the rule
JSONObject ruleActionJson = ruleJson.getJSONObject("action");
// if we're doing an update then the rule should already have
// this action set on it, so get the action object already on
// the rule
Action ruleActionToUpdate = null;
if (update == true)
{
String ruleActionJsonId = ruleActionJson.getString("id");
ruleActionToUpdate = rule.getAction();
// throw a web script exception if the ID of the rule's action,
// already persisted to the repository, is not the same as the one
// given for the rule action's ID in the rule details that we
// wish to perform the rule update with
if (ruleActionToUpdate.getId().equals(ruleActionJsonId) == false)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "The ID sent in the rule details "
+ "of the action directly associated with the rule we wish to update does not match "
+ " the rule's action already persisted in the repository. The rule's nodeRef is: '"
+ ruleNodeRefToUpdate + "', the action ID provided in the rule details is '"
+ ruleActionJsonId + "', and the ID for the rule's action already persisted in the"
+ " repository is '" + ruleActionToUpdate.getId() + "'");
}
}
Action action = getActionFromJson(ruleActionJson, ruleActionToUpdate);
rule.setAction(action);
}
} }
catch (JSONException je) catch (JSONException je)
{ {
throw new WebScriptException(Status.STATUS_BAD_REQUEST, throw new WebScriptException(Status.STATUS_BAD_REQUEST, "There was a problem reading the 'ruleTypes' "
"Problem creating rule from Rule Details sent in the request content.", je); + "property in the received Rule JSON. It may not be a JSON Array or one of the rule types "
+ "therein may contain invalid characters. The title of the offending rule is '"
+ ruleJson.optString("title") + "'", je);
}
if ((ruleJson.isNull("action") == true) && (update == false))
{
// the "action" field is mandatory, it is missing in the rule details,
// and we are creating a new rule so throw an exception
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "A new rule is being created but the 'action' "
+ "field, which is mandatory, has not been included in the rule details. The title of the "
+ "offending rule is '" + ruleJson.optString("title") + "'");
}
else
{
// set the action supplied in the rule details onto the rule
JSONObject ruleActionJson;
try
{
ruleActionJson = ruleJson.getJSONObject("action");
}
catch (JSONException je)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "There was a problem reading the 'action' "
+ "property in the received rule JSON. It is mandatory and may be missing from the "
+ "rule JSON. The title of the offending rule is '" + ruleJson.optString("title") + "'", je);
}
// if we're doing an update then the rule should already have
// this action set on it, so get the action object already on
// the rule
Action ruleActionToUpdate = null;
if (update == true)
{
String ruleActionJsonId;
try
{
ruleActionJsonId = ruleActionJson.getString("id");
}
catch (JSONException je)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "There was a problem reading the 'id' "
+ "property in the rule's root action from the received rule JSON. It is mandatory when "
+ "updating a rule and may be missing from the received rule JSON. The title of the "
+ "offending rule is '" + ruleJson.optString("title") + "'", je);
}
ruleActionToUpdate = rule.getAction();
// throw a web script exception if the ID of the rule's action,
// already persisted to the repository, is not the same as the one
// given for the rule action's ID in the rule details that we
// wish to perform the rule update with
if (ruleActionToUpdate.getId().equals(ruleActionJsonId) == false)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "The ID sent in the rule details "
+ "of the action directly associated with the rule we wish to update does not match "
+ " the rule's action already persisted in the repository. The rule's nodeRef is: '"
+ ruleNodeRefToUpdate + "', the action ID provided in the rule details is '"
+ ruleActionJsonId + "', and the ID for the rule's action already persisted in the"
+ " repository is '" + ruleActionToUpdate.getId() + "'");
}
}
Action action = getActionFromJson(ruleActionJson, ruleActionToUpdate);
rule.setAction(action);
} }
return rule; return rule;
@@ -316,7 +364,8 @@ public class RulesHelper
* then this indicates that this action is to be updated from the action details * then this indicates that this action is to be updated from the action details
* provided in the given JSON object and then returned. * provided in the given JSON object and then returned.
* If a 'null' is passed into this parameter, then this indicates that a new action is to * If a 'null' is passed into this parameter, then this indicates that a new action is to
* be created from scratch and returned. * be created from scratch, populated with the action details provided in the given JSON object
* and then returned.
* *
* @param actionJson the action JSON object used to create/update the action with * @param actionJson the action JSON object used to create/update the action with
* @param actionToUpdate The action to be updated. * @param actionToUpdate The action to be updated.
@@ -324,7 +373,6 @@ public class RulesHelper
* *
* @return The action created/updated from the given action JSON object * @return The action created/updated from the given action JSON object
*/ */
@SuppressWarnings("unchecked")
public Action getActionFromJson(JSONObject actionJson, Action actionToUpdate) public Action getActionFromJson(JSONObject actionJson, Action actionToUpdate)
{ {
ActionService actionService = this.serviceRegistry.getActionService(); ActionService actionService = this.serviceRegistry.getActionService();
@@ -336,156 +384,197 @@ public class RulesHelper
// //
Action action = null; Action action = null;
boolean updateAction = false;
// if an action has been given to update with fields present in the given action
// JSON object, then set that action to the current action, and set the updateAction
// indicator to true
if (actionToUpdate != null) if (actionToUpdate != null)
{ {
action = actionToUpdate; action = actionToUpdate;
updateAction = true;
} }
//
// create an action object from an "action" JSON object
//
String actionDefinitionName;
try
{
actionDefinitionName = actionJson.getString("actionDefinitionName");
}
catch (JSONException je)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "There was a problem reading the "
+ "'actionDefinitionName' property from the the received action JSON. It is mandatory "
+ "and may be missing from the received action JSON. The 'title' of the offending action is '"
+ actionJson.optString("title") + "'", je);
}
JSONArray nestedActionsJson = actionJson.optJSONArray("actions");
// if action's definition name denotes that it is a composite action and the
// action JSON object has nested actions, then treat it as a composite action
if ((actionDefinitionName.equals(COMPOSITE_ACTION_DEF_NAME)) == true && (nestedActionsJson != null))
{
// if we are updating an action which is a composite action,
// but the action definition name in the action JSON is not 'composite-action'
// throw a web script exception
if ((updateAction == true) && ((action instanceof CompositeAction) == false))
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "The action you wish to update "
+ "is not a composite action object, but the action definition name in the action JSON is "
+ "'composite-action'. Thus this action could not be updated with the action JSON sent");
}
// TODO remove this look-up map when the back-end provides an easy way to lookup actions
// on a composite action by ID
// if we are updating an existing composite action then create a map to easily look up the
// nested action objects for each nested action details provided in the action JSON object
Map<String, Action> nestedActionsMap = new HashMap<String, Action>();
if ((updateAction == true) && ((action instanceof CompositeAction) == true))
{
List<Action> nestedActions = ((CompositeAction)action).getActions();
for (Action nestedAction: nestedActions)
{
nestedActionsMap.put(nestedAction.getId(), nestedAction);
}
}
// else if we are not updating then create composite action object
// for scratch
else if (updateAction == false)
{
action = actionService.createCompositeAction();
}
// recursively add nested actions to this composite action
// as some of those nested actions could also be composite actions
int numNestedActionsJson = nestedActionsJson.length();
for (int i=0; i < numNestedActionsJson; i++)
{
JSONObject nestedActionJson = nestedActionsJson.optJSONObject(i);
if (nestedActionJson != null)
{
Action nestedAction = null;
// if we are doing an action update, then update the nested actions from
// the nested action JSON
if (updateAction == true)
{
String nestedActionJsonID;
try
{
nestedActionJsonID = nestedActionJson.getString("id");
}
catch (JSONException je)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "There was a problem reading the "
+ "'id' property from the received action JSON. It is mandatory when updating an action"
+ "and may be missing from the received action JSON. The 'title' of the offending action is '"
+ nestedActionJson.optString("title") + "'", je);
}
// lookup to see if nested action from nested action JSON
// already exists on composite action, in which case, update
// the nested action with the nested action details provided in the
// nested action JSON
Action nestedActionToUpdate = nestedActionsMap.get(nestedActionJsonID);
if (nestedActionToUpdate != null)
{
// first remove the nested action to be updated from the parent
// composite action
((CompositeAction)action).removeAction(nestedActionToUpdate);
// update that nested action with the details in the nested action JSON
nestedAction = getActionFromJson(nestedActionJson, nestedActionToUpdate);
}
}
// else we are not doing an action update so just pass in the
// actionToUpdate as 'null'
else
{
nestedAction = getActionFromJson(nestedActionJson, null);
}
// add the nested action (newly created or just updated) to
// the composite action
((CompositeAction)action).addAction(nestedAction);
}
}
}
// else if the action definition name denotes that this is not a composite action,
// but nested actions have been provided in the action JSON Object
// then throw a Web Script Exception
else if ((actionDefinitionName.equals(COMPOSITE_ACTION_DEF_NAME) == false) && (nestedActionsJson != null))
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Nested actions were sent in the action details "
+ "having Title: '" + actionJson.optString("title") + "', but the action definition "
+ "name thereof is not '" + COMPOSITE_ACTION_DEF_NAME + "' as expected. Instead, the action's "
+ "definition name is '" + actionDefinitionName + "'.");
}
// if we are not updating an existing action and there are no nested actions in the action JSON,
// just create a new action from the action definition without any recursive nested action handling
if ((updateAction == false) && (nestedActionsJson == null))
{
action = actionService.createAction(actionDefinitionName);
}
//
// set action properties
//
try try
{ {
// if ((actionJson.isNull("title") == true) && (updateAction == false))
// create an action object from an "action" JSON object
//
String actionDefinitionName = actionJson.getString("actionDefinitionName");
JSONArray nestedActionsJson = actionJson.optJSONArray("actions");
// if action's definition name denotes that it is a composite action and the
// action JSON object has nested actions, then treat it as a composite action
if ((actionDefinitionName.equals(COMPOSITE_ACTION_DEF_NAME)) == true && (nestedActionsJson != null))
{ {
// if we are updating an existing action and the given // the "title" field is missing in the action details,
// actionToUpdate is not a composite action, then throw a // and we are creating a new rule,
// web script exception // but the "title" field is mandatory, so throw an exception
if ((actionToUpdate != null) && ((actionToUpdate instanceof CompositeAction) == false))
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "The action directly associated with the "
+ "rule you wish to update is not a composite action. Thus this action could not be updated with "
+ "the given action JSON - the action details sent");
}
// TODO remove this look-up map when the back-end provides an easy way to lookup actions
// on a composite action by ID
// if we are updating an existing composite action then create a map to easily look up the
// nested action objects for each nested action details provided in the action JSON object
Map<String, Action> nestedActionsMap = new HashMap<String, Action>();
if ((actionToUpdate != null) && ((actionToUpdate instanceof CompositeAction) == true))
{
List<Action> nestedActions = ((CompositeAction)action).getActions();
for (Action nestedAction: nestedActions)
{
nestedActionsMap.put(nestedAction.getId(), nestedAction);
}
}
// else if we are not updating then create composite action object
// for scratch
else if (actionToUpdate == null)
{
action = actionService.createCompositeAction();
}
// recursively add nested actions to this composite action
// as some of those nested actions could also be composite actions
int numNestedActionsJson = nestedActionsJson.length();
for (int i=0; i < numNestedActionsJson; i++)
{
JSONObject nestedActionJson = nestedActionsJson.optJSONObject(i);
if (nestedActionJson != null)
{
Action nestedAction = null;
// if we are doing an action update, then update the nested actions from
// the nested action JSON
if (actionToUpdate != null)
{
String nestedActionJsonID = nestedActionJson.getString("id");
// lookup to see if nested action from nested action JSON
// already exists on composite action, in which case, update
// the nested action with the nested action details provided in the
// nested action JSON
Action nestedActionToUpdate = nestedActionsMap.get(nestedActionJsonID);
if (nestedActionToUpdate != null)
{
// remove the existing nested action to then be updated below with the
// updated one
nestedAction = getActionFromJson(nestedActionJson, nestedActionToUpdate);
}
}
// else we are not doing an action update so just pass in the
// actionToUpdate as 'null'
else
{
nestedAction = getActionFromJson(nestedActionJson, null);
}
((CompositeAction)action).addAction(nestedAction);
}
}
}
// else if the action definition name denotes that this is not a composite action,
// but nested actions have been provided in the action JSON Object
// then throw a Web Script Exception
else if ((actionDefinitionName.equals(COMPOSITE_ACTION_DEF_NAME) == false) && (nestedActionsJson != null))
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Nested actions were sent in the action details "
+ "having Title: '" + actionJson.optString("title") + "', but the action definition "
+ "name thereof is not '" + COMPOSITE_ACTION_DEF_NAME + "' as expected. Instead, the action's "
+ "definition name is '" + actionDefinitionName + "'.");
}
// else the action's definition name is 'composite-action' but no nested actions were provided in the action JSON
// (in which case we will just treat the action as a non-composite action anyway), otherwise the action is not
// defined as a composite action, and no nested actions were sent in the action JSON, so just create it as a
// non-composite action
else
{
action = actionService.createAction(actionDefinitionName);
}
//
// set action properties
//
if ((actionJson.isNull("title") == true) && (actionToUpdate == null))
{
// the "title" field is mandatory, it is missing in the rule details,
// and we are creating a new rule, so throw an exception
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "A new rule is being created but the 'title' " throw new WebScriptException(Status.STATUS_BAD_REQUEST, "A new rule is being created but the 'title' "
+ "field, which is mandatory, has not been included in the rule details"); + "field, which is mandatory, has not been included in the rule details");
} }
// otherwise go ahead and set the value if the field is present // otherwise go ahead and set the value if the field is present
// to cover both create and update scenarios
else if (actionJson.isNull("title") == false) else if (actionJson.isNull("title") == false)
{ {
action.setTitle(actionJson.getString("title")); action.setTitle(actionJson.getString("title"));
} }
}
if (actionJson.isNull("description") == false) catch (JSONException je)
{ {
action.setDescription(actionJson.optString("description")); throw new WebScriptException(Status.STATUS_BAD_REQUEST, "There was a problem reading the "
} + "'title' property from the received action JSON. It is mandatory and may be "
+ "missing from the received action JSON, or else it may contain invalid characters.", je);
// If a value has been provided in the action details for the "executeAsync" field }
// then set it to the action object.
// If the value given for a field does not equate to either if (actionJson.isNull("description") == false)
// 'true' or 'false', then set it to a default value of false {
action.setDescription(actionJson.optString("description"));
if (actionJson.isNull("executeAsync") == false) }
{
action.setExecuteAsynchronously(actionJson.optBoolean("executeAsync", false)); // If a value has been provided in the action details for the "executeAsync" field
} // then set it to the action object.
// If the value given for a field does not equate to either
// set compensating action on current action if a compensating action is present // 'true' or 'false', then set it to a default value of false
// in the action JSON Object
if (actionJson.isNull("executeAsync") == false)
{
action.setExecuteAsynchronously(actionJson.optBoolean("executeAsync", false));
}
// set compensating action on current action if a compensating action is present
// in the action JSON Object
try
{
if (actionJson.isNull("compensatingAction") == false) if (actionJson.isNull("compensatingAction") == false)
{ {
JSONObject compActionJson = actionJson.getJSONObject("compensatingAction"); JSONObject compActionJson = actionJson.getJSONObject("compensatingAction");
Action compActionToUpdate = null; Action compActionToUpdate = null;
if (actionToUpdate != null) if (updateAction)
{ {
compActionToUpdate = action.getCompensatingAction(); compActionToUpdate = action.getCompensatingAction();
} }
@@ -493,120 +582,186 @@ public class RulesHelper
action.setCompensatingAction(compAction); action.setCompensatingAction(compAction);
} }
// get the action's definition
ParameterizedItemDefinition actionDef = actionService.getActionDefinition(actionDefinitionName);
// if there are parameter values in the action JSON object then
// set them onto the action object
//
JSONObject actionParamValuesJson = actionJson.optJSONObject("parameterValues");
if (actionParamValuesJson != null)
{
setParameterValuesOnParameterizedItemFromJson(action, actionDef, actionParamValuesJson);
}
//
// set conditions on the current action
//
if (actionJson.isNull("conditions") == false)
{
JSONArray conditionsJson = actionJson.getJSONArray("conditions");
// if we are doing an update then build up a condition map
// do be able to do a condition look-up by ID for each condition included
// in the condition JSON - the condition details
Map<String, ActionCondition> conditionsMap = new HashMap<String, ActionCondition>();
if (actionToUpdate != null)
{
List<ActionCondition> actionConditions = actionToUpdate.getActionConditions();
for (ActionCondition actionCondition : actionConditions)
{
conditionsMap.put(actionCondition.getId(), actionCondition);
}
}
// get each condition and add it to the action
int numConditionsJson = conditionsJson.length();
for (int conditionJsonIndex = 0; conditionJsonIndex < numConditionsJson; conditionJsonIndex++)
{
ActionCondition condition = null;
JSONObject conditionJson = conditionsJson.getJSONObject(conditionJsonIndex);
String conditionDefName = null;
// if we are doing an update, then get the existing condition matching
// the condition ID given in the condition JSON, and update that with
// the condition fields given therein
if (actionToUpdate != null)
{
String conditionJsonId = conditionJson.getString("id");
condition = conditionsMap.get(conditionJsonId);
conditionDefName = condition.getActionConditionDefinitionName();
}
// we are not doing an update, so create the condition using the given condition
// definition name and then populate this new condition from the fields given in
// the condition JSON
else
{
// we are not doing an update, so if the conditionDefinitionName has not been provided
// in the condition JSON then throw a web script exception
if (conditionJson.isNull("conditionDefinitionName"))
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "A condition details at index: '"
+ conditionJsonIndex + "' for action ID '" + action.getId() + " could not be created "
+ "because the 'conditionDefinitionName' field is missing from the condition details sent");
}
// else condition def name has been provided in the condition details
else
{
conditionDefName = conditionJson.getString("conditionDefinitionName");
}
condition = actionService.createActionCondition(conditionDefName);
}
// get the condition definition object
ParameterizedItemDefinition conditionDef = actionService.getActionConditionDefinition(conditionDefName);
//
// set the condition's properties
//
// Set the value for the 'invertCondition' field if that field is sent
// in the condition JSON. If the value is sent, but it does not equate to
// either 'true' or 'false', then set it to a default value of false
if (conditionJson.isNull("invertCondition") == false)
{
condition.setInvertCondition(conditionJson.getBoolean("invertCondition"));
}
//
// if there are parameter values on the condition JSON object
// then apply them to the condition object
//
JSONObject condParamValuesJson = conditionJson.optJSONObject("parameterValues");
if (condParamValuesJson != null)
{
setParameterValuesOnParameterizedItemFromJson(condition, conditionDef, condParamValuesJson);
}
// add condition to action object
action.addActionCondition(condition);
// increment the condition JSON index
conditionJsonIndex++;
}
}
} }
catch (JSONException je) catch (JSONException je)
{ {
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "There was a problem reading the "
+ "'compensatingAction' property from the received action JSON. The value of the property "
+ "may not be a JSON Object or something may be wrong with one of the properties in the JSON "
+ "Object for the compensating action itself. The 'title' of the offending action is '"
+ actionJson.optString("title") + "'", je);
}
// get the action's definition
ParameterizedItemDefinition actionDef = actionService.getActionDefinition(actionDefinitionName);
// if there are parameter values in the action JSON object then
// set them onto the action object
//
JSONObject actionParamValuesJson = actionJson.optJSONObject("parameterValues");
if (actionParamValuesJson != null)
{
setParameterValuesOnParameterizedItemFromJson(action, actionDef, actionParamValuesJson);
}
//
// set conditions on the current action
//
// if action JSON "conditions" property has a value
// then populate the current action's conditions with the
// conditions' details from within the action JSON
if (actionJson.isNull("conditions") == false)
{
JSONArray conditionsJson = actionJson.optJSONArray("conditions");
// if conditionsJson is 'null' then throw a web script exception, because this means that
// the conditions property does not contain a JSON Array. The conditions property of an incoming
// action JSON object should be a JSON Array
if (conditionsJson == null)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "The 'conditions' property of the incoming "
+ "action JSON titled '" + actionJson.optString("title") + "' is not a JSON Array");
}
throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, // If we are updating an existing action, then build up a map
"Problem creating rule from JSON passed into Web Script.", je); // (keyed by condition ID) of conditions associated with that existing action.
// So for each condition JSON object (inside the incoming action JSON object),
// if the condition ID thereof is found in the map, then update the existing condition
// with the details sent in the JSON
Map<String, ActionCondition> conditionsMap = new HashMap<String, ActionCondition>();
if (updateAction == true)
{
List<ActionCondition> actionConditions = action.getActionConditions();
for (ActionCondition actionCondition : actionConditions)
{
conditionsMap.put(actionCondition.getId(), actionCondition);
}
}
//
// for each condition JSON object (associated with the incoming action JSON object):
// - if we are doing an update then update the corresponding condition object (if one exists)
// with the fields provided in the condition JSON object
// - if we are doing a create then create a new condition from the details provided
// in the condition JSON
int numConditionsJson = conditionsJson.length();
for (int conditionJsonIndex = 0; conditionJsonIndex < numConditionsJson; conditionJsonIndex++)
{
ActionCondition condition = null;
JSONObject conditionJson;
try
{
conditionJson = conditionsJson.getJSONObject(conditionJsonIndex);
}
catch (JSONException je)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "There was a problem reading the "
+ "condition held at index " + conditionJsonIndex + " in the JSON Array held in the "
+ "'conditions' property from the received action JSON. The value held at that "
+ "index may not be a JSON Object. The 'title' of the action with the offending "
+ "'conditions' property is '" + actionJson.optString("title") + "'", je);
}
String conditionDefName = null;
// if we are doing an update, the current condition JSON has an ID,
// and a condition already exists matching that ID, then set the current
// condition to that existing condition and retrieve its definition name
if ((updateAction == true) && (conditionJson.isNull("id") == false))
{
String conditionJsonId;
try
{
conditionJsonId = conditionJson.getString("id");
}
catch (JSONException je)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "There was a problem reading the "
+ "'id' property from a condition in the received action JSON. When doing an update "
+ "this condition property is mandatory and may be missing from this condition in the "
+ "action JSON sent or else the property may contain invalid parameters. "
+ "The 'conditionDefinitionName' of the offending condition is '"
+ conditionJson.optString("conditionDefinitionName") + "'", je);
}
// set the current condition being processed to the existing conditions
condition = conditionsMap.get(conditionJsonId);
// get the condition definition name
if (condition != null)
{
conditionDefName = condition.getActionConditionDefinitionName();
}
// remove the condition to be updated from its parent action
// The updated condition is added to the action at the end of the
// loop
action.removeActionCondition(condition);
}
// if the current condition is still 'null' (we are not updating an existing condition),
// and if the conditionDefinitionName has not been provided in the condition JSON, then
// throw a web script exception because we need to create a new condition using the condition
// definition name provided in the condition JSON object
if ((condition == null) && (conditionJson.isNull("conditionDefinitionName")))
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "A condition details at index: '"
+ conditionJsonIndex + "' for action ID '" + action.getId() + " could not be created "
+ "because the 'conditionDefinitionName' field is missing from the condition details sent");
}
// else condition def name has been provided in the condition details
if (condition == null)
{
try
{
conditionDefName = conditionJson.getString("conditionDefinitionName");
}
catch (JSONException je)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "There was a problem reading the "
+ "'conditionDefinitionName' property from a condition in the received action JSON. "
+ "This condition property is mandatory and may be missing from this condition in the "
+ "action JSON sent. The 'conditionDefinitionName' of the offending condition is '"
+ conditionJson.optString("conditionDefinitionName") + "'", je);
}
condition = actionService.createActionCondition(conditionDefName);
}
// get the condition definition object
ParameterizedItemDefinition conditionDef = actionService.getActionConditionDefinition(conditionDefName);
//
// populate the condition (newly created, or one being updated)
// with fields given in the condition JSONs the condition's properties
//
// Set the value for the 'invertCondition' field if that field is sent
// in the condition JSON. If the value is sent, but it does not equate to
// either 'true' or 'false', then set it to a default value of false
if (conditionJson.isNull("invertCondition") == false)
{
condition.setInvertCondition(conditionJson.optBoolean("invertCondition"));
}
//
// if there are parameter values on the condition JSON object
// then apply them to the condition object
//
JSONObject condParamValuesJson = conditionJson.optJSONObject("parameterValues");
if (condParamValuesJson != null)
{
setParameterValuesOnParameterizedItemFromJson(condition, conditionDef, condParamValuesJson);
}
// add condition to action object
action.addActionCondition(condition);
}
} }
return action; return action;

View File

@@ -133,7 +133,7 @@ public class RulesPost extends DeclarativeWebScript
// URL template tokens // URL template tokens
NodeRef owningNodeRef = this.rulesHelper.getNodeRefFromWebScriptUrl(req, storeType, storeId, id); NodeRef owningNodeRef = this.rulesHelper.getNodeRefFromWebScriptUrl(req, storeType, storeId, id);
// apply rule to actionable node // apply rule to rule owning node
this.ruleService.saveRule(owningNodeRef, rule); this.ruleService.saveRule(owningNodeRef, rule);
// add objects to model for the template to render // add objects to model for the template to render