例 13: 条件値とアクションをデシジョン・テーブルに追加する

この例では、条件値とアクションをデシジョン・テーブルに追加します。 条件値は、テンプレートを使用してデシジョン・テーブルに追加できます。

条件値を条件ノードに追加すると、ケース・エッジを追加することになります。新しいケース・エッジは、ケース・エッジのリストの最後に追加されます。 条件値を追加するためには、適切なパラメーター値を設定したテンプレート・インスタンス式を指定する必要があります。 テンプレート・インスタンス式を指定するためには、特定のテンプレートを使用する必要があります。 テンプレートの名前は、条件ノードのレベルごとに固有の名前を付けることをお勧めします。これにより、該当するタイプの条件に合った正しいテンプレートを取得できます。 単一のテンプレート定義を使用すると、条件を追加するレベルの判別が困難になるおそれがあります。

条件値を条件ノードに設定すると、同じテンプレート・インスタンスを持つ条件値を、同じレベルにあるすべての条件ノードに追加することになります。これは、デシジョン・テーブルが平衡型であるためです。 また、新しい条件値を追加すると、この操作の一環として新しいアクション・ノードも追加されます。 これらのアクション・ノードは、ユーザー表示およびテンプレート・インスタンス式にヌルの値が指定されたツリー・アクションを持ちます。 条件値は、アクション・ノードを子ノードとして持たない条件ノードに追加できるため、条件ノードの追加によって、アクション・ノードが大幅に増える場合があります。 アクション・ノードの数は、条件ノードを追加するレベル、そのレベルにある条件ノードの数、および子レベルそれぞれにある条件ノードの数に応じます。

作成されたアクション・ノードを見つけるには、ユーザー表示およびテンプレート・インスタンス式がヌルのツリー・アクションを持つアクション・ノードの検索を実行します。 TreeAction に設定可能な式を作成するには、TreeActionValueTemplate を使用します。 このパターンを、すべての新しいアクション・ノードに対して繰り返す必要があります。

この例には、新規ツリー・アクションのセットアップを支援する 2 つのメソッドが提供されています。 getEmptyActionNode は、現行の条件ノードから空のアクション・ノードを再帰的に検索します。getParameterValue は、名前で指定されたパラメーターの値を返します。

package com.ibm.websphere.sample.brules.mgmt;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.ibm.wbiserver.brules.mgmt.BusinessRule;
import com.ibm.wbiserver.brules.mgmt.BusinessRuleGroup;
import com.ibm.wbiserver.brules.mgmt.BusinessRuleManagementException;
import com.ibm.wbiserver.brules.mgmt.BusinessRuleManager;
import com.ibm.wbiserver.brules.mgmt.Operation;
import com.ibm.wbiserver.brules.mgmt.Parameter;
import com.ibm.wbiserver.brules.mgmt.ParameterValue;
import com.ibm.wbiserver.brules.mgmt.Template;
import com.ibm.wbiserver.brules.mgmt.ValidationException;
import com.ibm.wbiserver.brules.mgmt.dtable.ActionNode;
import com.ibm.wbiserver.brules.mgmt.dtable.CaseEdge;
import com.ibm.wbiserver.brules.mgmt.dtable.ConditionNode;
import com.ibm.wbiserver.brules.mgmt.dtable.DecisionTable;
import com.ibm.wbiserver.brules.mgmt.dtable.TemplateInstanceExpression;
import com.ibm.wbiserver.brules.mgmt.dtable.TreeAction;
import com.ibm.wbiserver.brules.mgmt.dtable.TreeActionTermDefinition;
import com.ibm.wbiserver.brules.mgmt.dtable.TreeActionValueTemplate;
import com.ibm.wbiserver.brules.mgmt.dtable.TreeBlock;
import com.ibm.wbiserver.brules.mgmt.dtable.TreeConditionValueTemplate;
import com.ibm.wbiserver.brules.mgmt.dtable.TreeNode;
import com.ibm.wbiserver.brules.mgmt.problem.Problem;
import com.ibm.wbiserver.brules.mgmt.query.QueryOperator;

public class Example13
{
	static Formatter out = new Formatter();

	static public String executeExample13()
	{
		try
		{
			out.clear();

			// Retrieve a business rule group by target namespace
			// and name
			List<BusinessRuleGroup> brgList = BusinessRuleManager
				.getBRGsByTNSAndName(
			"http://BRSamples/com/ibm/websphere/sample/brules",
					QueryOperator.EQUAL,"ConfigurationValues",
					QueryOperator.EQUAL, 0, 0);

			if (brgList.size() > 0)
				{
					// Get the first business rule group from the
					// list. This should be the only business
					// rule group in the list as the combination
					// of target namespace and name are unique
					BusinessRuleGroup brg = brgList.get(0);

					// Get the operation of the business rule
					// group that has the business rule that will
					// be modified as the business rules are
					// associated with a specific operation
					Operation op = brg.getOperation("getMessages");

					// Get all business rules available for
					// this operation
					List<BusinessRule> ruleList =
						op.getAvailableTargets();

					// For this operation there is only 1 business
					// rule and it is the business that we want
					// to update

					DecisionTable decisionTable = (DecisionTable)
						ruleList.get(0);
						out.printlnBold("Decision table before
						publish:");
						out.print(RuleArtifactUtility
						.printDecisionTable(decisionTable));
条件値を追加するレベルを見つける必要があります。 クラスを使用するユーザー・インターフェースまたはアプリケーションは、どこに条件を追加するかを認識しているため、このレベルは通常、パラメーターとして渡されます。
					// Get the tree block that contains all of
					// the conditions and actions for the decision
					// table
					TreeBlock treeBlock =
						decisionTable.getTreeBlock();

					// From the tree block, get the tree node which
					// is the starting point for navigating through
					// the decision table
					ConditionNode conditionNode = (ConditionNode)
						treeBlock.getRootNode();

					// Get the case edges for this node which is
					// the first level of conditions
					List<CaseEdge> caseEdges =
						conditionNode.getCaseEdges();

					// Get the case edge which will have the new
					// condition added
					CaseEdge caseEdge = caseEdges.get(0);

					// For the case edge get the condition node in
					// order to retrieve the templates for the
					// condition
					conditionNode = (ConditionNode)
									caseEdge.getChildNode();

					// Get the templates for the condition
					List<TreeConditionValueTemplate>
						treeValueConditionTemplates = conditionNode
						.getAvailableValueTemplates();

					Iterator<TreeConditionValueTemplate>
						treeValueConditionTemplateIterator =
						treeValueConditionTemplates.iterator();

					TreeConditionValueTemplate conditionTemplate =
						null;
デシジョン・テーブルの各条件ノード・レベルで固有のテンプレート名を使用することで、より簡単に正しい条件ノード値に条件値を追加できます。
					// Find the template that should be used
						while
					(treeValueConditionTemplateIterator.hasNext())
					{
						conditionTemplate =
							treeValueConditionTemplateIterator
								.next();
						if (conditionTemplate.getName().equals(
							"Condition Value Template
							2.1"))
							{
								// Template found
								break;
							}
							conditionTemplate = null;
					}
					if (conditionTemplate != null)
					{
正しいテンプレートが検出された後、インスタンスを作成して適切なパラメーター値を設定してから、条件ノードに追加します。
					// テンプレートからパラメーター定義を
					// 取得します。
					Parameter conditionParameter =
					conditionTemplate.getParameter("param0");

					// 新しい条件テンプレート・インスタンスで
					// 使用するパラメーター値インスタンスを
					// 取得元と
					ParameterValue conditionParameterValue =
							conditionParameter
							.createParameterValue("fatal");

					List<ParameterValue>
							conditionParameterValues = new
							ArrayList<ParameterValue>();

					// Add the parameter value to a list

					conditionParameterValues
						.add(conditionParameterValue);

					// Create a new condition template
					// instance with the parameter value
					TemplateInstanceExpression
						newConditionValue =
						conditionTemplate
							.createTemplateInstanceExpression(c
						onditionParameterValues);
					// Add the condition template instance to
					// this condition node
					conditionNode

					.addConditionValueToThisLevel(newConditionValue);
					// When a condition node is added there
					// are new action nodes that are created
					// and empty. These must be filled with
					// action template instances. By
					// searching for each empty action
					// node from the parent level, all of the
					// new empty action nodes can be found.
					conditionNode = (ConditionNode)
					conditionNode.getParentNode();
条件値を条件ノードに追加した後は、TreeActionValueTemplate を使用して、新規アクション・ノードのツリー・アクションを設定する必要があります。 まず、ケース・エッジの空のアクション・ノードを見つけます。 親条件ノードを使用することで、条件ノードの繰り返し処理によってすべてのアクション・ノードが確実に検索されるようにします。
					// Get the case edges for the parent node
					caseEdges = conditionNode.getCaseEdges();

					Iterator<CaseEdge> caseEdgesIterator =
					caseEdges.iterator();

					while (caseEdgesIterator.hasNext())
					{
						// For each case edge, retrieve an
						// empty action node if it exists
						ActionNode actionNode =
						getEmptyActionNode(caseEdgesIterator
						.next());

						// Check if all actions are filled
						if (actionNode != null)
						{
ツリー・アクションが空のアクション・ノードが検出された場合には、TreeActionValueTemplate を使用してツリー・アクションを設定する必要があります。 まずテンプレートを見つけて、パラメーターを指定してからテンプレート・インスタンスを作成します。 テンプレート・インスタンスが作成されたら、ツリー・アクションを更新できます。 この例では、同じ条件ノードの下にある別のアクション・ノードの別のツリー・アクションの値を使用して、パラメーターを設定しています。 新規パラメーター値の作成に使用できる値が別のツリー・アクションに存在しない別のデシジョン・テーブルの場合は、アプリケーションによって値をパラメーターとして渡す必要があります。
							// ツリー・アクションのリストを
							// 取得します。これらは
							// 実際のアクションでは
							// なく、アクションの
							// プレースホルダー
							// 取得します
							List<TreeAction>
							treeActionList = actionNode
								.getTreeActions();

							List<TreeActionTermDefinition>
							treeActionTermDefinitions =
								treeBlock
							.getTreeActionTermDefinitions();

							List<TreeActionValueTemplate>
								treeActionValueTemplates =
								treeActionTermDefinitions
								.get(0).getValueTemplates();

							TreeActionValueTemplate
								actionTemplate = null;

							for (TreeActionValueTemplate
									tempActionTemplate :
									treeActionValueTemplates)
									{

									if
									(tempActionTemplate.get
										Name().equals(
										"Action Value
										Template 1"))
										{
											actionTemplate =
											tempActionTemplate;
											break;
										}
									}

									if (actionTemplate != null)
									{
										// 新規アクション・
										// ノードでエラー・
										// メッセージの
										// 基準として、
										// 値を使用するには、
										// 親条件ノードの
										// 下にある
										// 別のアクションを
										// action node. まず
										// 親条件
										// parent condition
										// 移動します
										ConditionNode
										parentNode =
										(ConditionNode)
										actionNode
											.getParentNode();

										// 新規アクションが
										// ケース・エッジ・
										// リストの末尾に
										// 追加されるときに、
										// 親ノードの最初の
										// ケース・エッジが常に
										// 設定されるため、
										// このアクションを
										// edge list.
										CaseEdge caseE =
											parentNode.getCas
											eEdges().get(
											0);

										// 下位ノードは
										// アクション・ノードで
										// 新しいアクション・ノードと
										// 同じレベルに
										// action node.
										ActionNode aNode =
										(ActionNode) caseE
											.getChildNode();

										// ツリー・アクションのリストを
										// 取得します
										TreeAction
											existingTreeAction =
											aNode
											.getTreeActions()
											.get(0);

										// パラメーターの
										// 取得元と
										// することができる
										// ツリー・アクションの
										// テンプレート・
										// インスタンス式を
										// 取得します

										TemplateInstanceExpression
										existingExpression =
											existingTreeAction
											.getValueTemplateInstance();

										ParameterValue
										existingParameterValue =
										getParameterValue(
												"param0",
										existingExpression);

										String actionValue =
										existingParameterValue
											.getValue();

										// 既存のツリー・アクションの
										// メッセージから
										// 新規の
										// メッセージを
										// ツリー・アクションの
										actionValue = "Fatal"
												+
										actionValue.substring(actionValue
											.indexOf(":"), actionValue
											.length());
											パラメーター
											actionParameter =
											actionTemplate
											.getParameter("param0");

											// Get the parameter
											// from the template
											ParameterValue
											actionParameterValue =
												actionParameter
											.createParameterValue(actionValue);

											// Add the parameter to
											// a list of templates
											List<ParameterValue>
											actionParameterValues = new
											ArrayList<ParameterValue>();

									actionParameterValues.add(actionParameterValue);

											// Create a new tree
											// action instance

										TemplateInstanceExpression
											treeAction = actionTemplate
					.createTemplateInstanceExpression(actionParameterValues);

										// Set the tree action
										// in the action node
										// by setting it in the
										// tree action list
ここで、アクション・ノード内のツリー・アクションが更新されます。
										treeActionList.get(0)
										.setValueTemplateInstance(
										treeAction);
										}
									}
							}
				}
				// With the condition value and actions
				// updated, the business rule group can be
				// published.
				// Use the original list or create a new list
				// of business rule groups
					List<BusinessRuleGroup> publishList = new
						ArrayList<BusinessRuleGroup>();

				// Add the changed business rule group to the
			list
				// list
					publishList.add(brg);

				// Publish the list with the updated business
				// rule group

				BusinessRuleManager.publish(publishList, true);

				brgList =
					BusinessRuleManager.getBRGsByTNSAndName(
					"http://BRSamples/com/ibm/websphere/sample/brules",
					QueryOperator.EQUAL, "ConfigurationValues",
					QueryOperator.EQUAL, 0, 0);
					brg = brgList.get(0);
					op = brg.getOperation("getMessages");
					ruleList = op.getAvailableTargets();
					decisionTable = (DecisionTable)
						ruleList.get(0);
					out.printlnBold("Decision table after
						publish:");
					out
						.print(RuleArtifactUtility
							.printDecisionTable(decisionTable));
				}
		} catch (ValidationException e)
		{
			List<Problem> problems = e.getProblems();

			out.println("Problem = " +
			problems.get(0).getErrorType().name());

			e.printStackTrace();
			out.println(e.getMessage());
		} catch (BusinessRuleManagementException e)
		{
			e.printStackTrace();
			out.println(e.getMessage());
		}
		return out.toString();
	}

	/*
	* このメソッドは、現行のケース・エッジから、空のツリー・
	* アクションを持つすべてのアクション・ノードを検索します。An empty
	* action node is found by looking at the end of the list
	* of case edges and checking if the action node has tree
	* actions that have both a null user presentation and
	* TemplateInstanceExpression.
	*/
	private static ActionNode getEmptyActionNode(CaseEdge next)
	{
		ActionNode actionNode = null;
		TreeNode treeNode = next.getChildNode();

	if (treeNode instanceof ConditionNode)
	{
		List<CaseEdge> caseEdges = ((ConditionNode) treeNode)
			.getCaseEdges();

		if (caseEdges.size() > 1)
		{
			// Get right-most case-edge as the new
			// condition and thus empty actions are at the
			// right-end of the case edges
			actionNode = getEmptyActionNode(caseEdges
				.get(caseEdges.size() - 1));

			if (actionNode != null)
			{
				return actionNode;
			}
	}
	} else
	{
		actionNode = (ActionNode) treeNode;

		List<TreeAction> treeActions =
		actionNode.getTreeActions();

		if (!treeActions.isEmpty())
		{
		if
		((treeActions.get(0).getValueUserPresentation() == null)
			&&
		(treeActions.get(0).getValueTemplateInstance() == null))
			{
				return actionNode;
			}
		}	
			`actionNode = null;
		}
		return actionNode;
	}
	/*
	このメソッドは、式の異なるパラメーター値をチェックし、
正しいパラメーターが見つかると、そのパラメーターの値を返します。
	*/
	private static ParameterValue getParameterValue(String pName,
			TemplateInstanceExpression expression)
	{
		ParameterValue parameterValue = null;

		// Check that the expression is not null as null would
		// indicate that the expression that was passed in was
		// probably not defined with a template and does not have
		// any parameters to check.
		if (expression != null)
		{
			// Get the parameter vlues for the expression
			List<ParameterValue> parameterValues = expression
				.getParameterValues();
			Iterator<ParameterValue> parameterIterator =
				parameterValues
				.iterator();

			// For the different parameters, check that it
			// matches the parameter value sought
			while (parameterIterator.hasNext())
			{
				parameterValue = parameterIterator.next();

				if
				(parameterValue.getParameter().getName().equals(pName))
				{
				// Return the parameter value that
				// matched
				return parameterValue;
				}
		}
	}
	return parameterValue;
}
}

例 13 の Web ブラウザー出力です。

Executing example13

Decision table before publish:
Decision Table
Name: getMessages
Namespace: http://BRSamples/com/ibm/websphere/sample/brules

Decision table after publish:
Decision Table
Name: getMessages
Namespace: http://BRSamples/com/ibm/websphere/sample/brules