You are viewing a plain text version of this content. The canonical link for it is here.
Posted to taglibs-dev@jakarta.apache.org by ra...@apache.org on 2005/08/10 23:11:40 UTC
svn commit: r231329 [7/13] - in /jakarta/taglibs/proper/rdc/trunk/src:
META-INF/tags/rdc/ org/apache/taglibs/rdc/ org/apache/taglibs/rdc/core/
org/apache/taglibs/rdc/dm/ org/apache/taglibs/rdc/resources/
org/apache/taglibs/rdc/sampleapps/mortgage/ org/...
Modified: jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/dm/RuleBasedDirectedDialog.java
URL: http://svn.apache.org/viewcvs/jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/dm/RuleBasedDirectedDialog.java?rev=231329&r1=231328&r2=231329&view=diff
==============================================================================
--- jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/dm/RuleBasedDirectedDialog.java (original)
+++ jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/dm/RuleBasedDirectedDialog.java Wed Aug 10 14:10:59 2005
@@ -66,793 +66,793 @@
* @author Rahul Akolkar
*/
public class RuleBasedDirectedDialog extends DialogManagerImpl {
-
- private static final String XPATH_NAVIGATION =
- "*/navigation";
- private static final String XPATH_CONDITION =
- "/dm-config/ruleset-def/conditions-list/condition-def";
-
- private Navigation navigation = null;
-
- private LinkedHashMap lruCache = new LinkedHashMap();
- private List tempVars = new ArrayList();
-
- // Error messages (to be i18n'zed)
- private static final String ERR_TRANS_EXP = "Transformer Exception " +
- "while trying to evaluate XPath expression: \"{0}\", with error " +
- "message \"{1}\"";
- private static final String ERR_DIGESTER_FAIL = "<!-- Error parsing " +
- "XML navigation rules for group: \"{0}\", with message: \"{1}\" -->\n";
- private static final String ERR_NULL_RULES = "<!-- Error parsing XML " +
- "navigation rules for group: \"{0}\" -->\n";
- private static final String ERR_IO_NULL_RULES = "<!-- IOException while" +
- " reporting null navigation rules for group with ID \"{0}\" -->\n";
- private static final String ERR_IO_RULES_HEALTH = "<!-- IOException " +
- "while reporting health of navigation rules for group with ID \"{0}\"" +
- " -->\n";
-
- // Logging
- private static Log log = LogFactory.getLog(RuleBasedDirectedDialog.class);
-
- /* Constructor */
- public RuleBasedDirectedDialog() {
- super();
- }
-
- public boolean initialize(JspContext ctx, JspFragment bodyFragment)
- throws JspException, IOException {
-
- boolean retVal = super.initialize(ctx, bodyFragment);
-
- GroupModel groupModel = (GroupModel) stateMap.get(groupTag.getId());
- if (groupModel.getInstanceData() != null) {
- navigation = (Navigation) groupModel.getInstanceData();
- return retVal;
- }
-
- Digester digester = new Digester();
- digester.setErrorHandler(new NavigationRulesErrorHandler());
-
- digester.addObjectCreate(XPATH_NAVIGATION, Navigation.class);
- digester.addObjectCreate(XPATH_NAVIGATION + "/initial",
- NavigationRule.class);
- digester.addSetProperties(XPATH_NAVIGATION + "/initial",
- new String[] {"target", "defaultTarget"},
- new String[] {"target", "defaultTarget"});
- digester.addObjectCreate(XPATH_NAVIGATION + "/initial/condition",
- ConditionImpl.class);
- digester.addSetProperties(XPATH_NAVIGATION + "/initial/condition",
- new String[] {"lvalue", "operation", "rvalue", "target"},
- new String[] {"lvalue", "operation", "rvalue", "target"});
- digester.addSetNext(XPATH_NAVIGATION + "/initial/condition",
- "addCondition" );
- digester.addSetNext(XPATH_NAVIGATION + "/initial","addNavigationRule");
-
- digester.addObjectCreate(XPATH_NAVIGATION + "/rule",
- NavigationRule.class);
- digester.addSetProperties(XPATH_NAVIGATION + "/rule",
- new String[] {"from", "target", "defaultTarget"},
- new String[] {"from", "target", "defaultTarget"});
- digester.addObjectCreate(XPATH_NAVIGATION + "/rule/condition",
- ConditionImpl.class);
- digester.addSetProperties(XPATH_NAVIGATION + "/rule/condition",
- new String[] {"lvalue", "operation", "rvalue", "target"},
- new String[] {"lvalue", "operation", "rvalue", "target"});
- digester.addSetNext(XPATH_NAVIGATION + "/rule/condition",
- "addCondition");
- digester.addSetNext(XPATH_NAVIGATION + "/rule", "addNavigationRule" );
-
- DOMParser dp = new DOMParser();
- final String rules = groupTag.getConfig();
- InputSource is1 = getRulesAsInputSource(null, ctx, rules);
- try {
- dp.parse(is1);
- } catch (SAXException sx) {
- throw new IOException("Cannot parse the config: " +
- groupTag.getConfig());
- } // end of try-catch
- Document d = dp.getDocument();
- NodeList conditionsList = null;
- try {
- conditionsList = XPathAPI.selectNodeList(d.getDocumentElement(),
- XPATH_CONDITION);
- } catch (TransformerException t) {
- MessageFormat msgFormat = new MessageFormat(ERR_TRANS_EXP);
- String errMsg = msgFormat.format(new Object[] {XPATH_CONDITION,
- t.getMessage()});
- log.error(errMsg);
- ((PageContext) ctx).getOut().write(errMsg);
- }
-
- if (conditionsList != null) {
- Set conditionNames = new HashSet();
- conditionNames.add("condition");
- for (int i = 0; i < conditionsList.getLength(); i++) {
- String name = name = ((Element)conditionsList.item(i)).
- getAttribute("name");
- RDCUtils.mustExist(name, "RuleBasedDirectedDialog: Cannot" +
- " add condition with empty name");
- RDCUtils.mustSatisfy(!conditionNames.contains(name),
- "RuleBasedDirectedDialog: Cannot add condition with " +
- "name \"" + name + "\" since a condition with that " +
- "name is already defined.");
- String impl = ((Element)conditionsList.item(i)).
- getAttribute("impl");
- RDCUtils.mustExist(impl, "RuleBasedDirectedDialog: Cannot" +
- " add condition with empty impl");
- Class implClass = RDCUtils.getClass(impl);
- if (implClass == null) {
- continue;
- }
- RDCUtils.mustSatisfy(RDCUtils.implementsInterface(implClass,
- Condition.class), "RuleBasedDirectedDialog: Cannot" +
- " add condition with name \"" + name + "\". Impl:" +
- impl + " does not implement the RuleBasedDirectedDialog." +
- "Condition interface.");
- RDCUtils.mustSatisfy(RDCUtils.hasMethod(implClass,
- "getAttrPropMap", null), "RuleBasedDirectedDialog: Cannot"+
- " add condition with name \"" + name + "\" since" +
- " the impl class " + impl + " does not define an" +
- " accessible method \"static Map getAttrPropMap()\"");
- Method m = null;
- Map attrPropMap = null;
- try {
- m = implClass.getMethod("getAttrPropMap", null);
- attrPropMap = (Map) m.invoke(null, null);
- } catch (Exception e) {
- RDCUtils.warnIf(true, "RuleBasedDirectedDialog: Could not" +
- " invoke getAttrPropMap() method of class: " + impl);
- continue;
- }
- Object[] keysArray = attrPropMap.keySet().toArray();
- String[] attrs = new String[keysArray.length];
- String[] props = new String[keysArray.length];
- for (int j = 0; j < keysArray.length; j++) {
- attrs[j] = (String) keysArray[j];
- RDCUtils.mustExist(attrs[j], "RuleBasedDirectedDialog: " +
- "Cannot add condition element with empty attribute");
- props[j] = (String) attrPropMap.get(attrs[j]);
- RDCUtils.mustExist(attrs[j], "RuleBasedDirectedDialog: " +
- "Attribute " + attrs[j] + " of condition with name " +
- name +" is not mapped to a property of class " + impl);
- RDCUtils.mustSatisfy(RDCUtils.hasField(implClass, props[j]),
- "RuleBasedDirectedDialog: Attribute " + attrs[j] +
- " of condition with name " + name + " is mapped " +
- "to a property " + props[j] + ", which does not " +
- "exist in the impl class " + impl);
- }
- digester.addObjectCreate(XPATH_NAVIGATION + "/initial/" + name,
- impl);
- digester.addSetProperties(XPATH_NAVIGATION + "/initial/" +name,
- attrs, props);
- digester.addSetNext(XPATH_NAVIGATION + "/initial/" + name,
- "addCondition");
- digester.addObjectCreate(XPATH_NAVIGATION + "/rule/" + name,
- impl);
- digester.addSetProperties(XPATH_NAVIGATION + "/rule/" + name,
- attrs, props);
- digester.addSetNext(XPATH_NAVIGATION + "/rule/" + name,
- "addCondition" );
- conditionNames.add(name);
- }
- }
-
- InputSource is2 = getRulesAsInputSource(digester, ctx, rules);
- try {
- navigation = (Navigation) digester.parse(is2);
- } catch (Exception e) {
- retVal = false;
- MessageFormat msgFormat = new MessageFormat(ERR_DIGESTER_FAIL);
- String errMsg = msgFormat.format(new Object[] {groupTag.
- getConfig(), e.getMessage()});
- log.error(errMsg);
- ((PageContext) ctx).getOut().write(errMsg);
- }
- groupModel.setInstanceData(navigation);
-
- return retVal;
- }
-
- /**
- * Collect the required information from the user
- *
- *
- */
- public void collect(JspContext ctx, JspFragment bodyFragment)
- throws JspException, IOException {
-
- checkRuleSetStatus();
-
- GroupModel groupModel = (GroupModel) stateMap.get(groupTag.getId());
- Map modelMap = groupModel.getLocalMap();
-
- if (modelMap.get(Constants.STR_INIT_ONLY_FLAG) == Boolean.TRUE) {
- // Start off with all children in dormant state
- setStateChildren(modelMap, Constants.FSM_DORMANT);
- groupState = Constants.GRP_ALL_CHILDREN_DORMANT;
- groupModel.setState(Constants.GRP_STATE_RUNNING);
- modelMap.put(Constants.STR_INIT_ONLY_FLAG, Boolean.FALSE);
- }
-
- if (groupModel.getState() == Constants.GRP_STATE_RUNNING) {
- do {
- dialogManager(groupTag);
- if (bodyFragment != null) {
- bodyFragment.invoke(null);
- }
- } while (renderNextChild(groupModel));
- }
- }
-
- /**
- * Check the health of the navigation rule set, and provide
- * client feedback for error conditions.
- *
- * @param navigation The Navigation rule set
- */
- private void checkRuleSetStatus() {
-
- if (navigation == null) {
- try {
- MessageFormat msgFormat = new MessageFormat(ERR_NULL_RULES);
- String errMsg = msgFormat.format(new Object[] {groupTag.
- getConfig()});
- log.error(errMsg);
- ((PageContext) groupTag.getJspContext()).getOut().
- write(errMsg);
- } catch (IOException ioe) {
- MessageFormat msgFormat = new MessageFormat(ERR_IO_NULL_RULES);
- log.error(msgFormat.format(new Object[] {groupTag.getId()}));
- }
- return;
- }
-
- String navHealth = (String)navigation.get(Navigation.
- NAV_RULE_SET_CREATION);
- StringBuffer strbuf = new StringBuffer("<!--");
- if (navHealth == null) {
- strbuf.append("The initial navigation rule");
- } else if (!navHealth.equals(Navigation.NAV_SUCCESS)) {
- strbuf.append("The navigation rule originating from component " +
- "with ID \"" + navHealth + "\"");
- } else {
- return;
- }
- strbuf.append(" has been overwritten. Correct the XML navigation " +
- "rule set in " + groupTag.getConfig() + " -->\n");
-
- try {
- ((PageContext) groupTag.getJspContext()).getOut().
- write(strbuf.toString());
- } catch (IOException ioe) {
- MessageFormat msgFormat = new MessageFormat(ERR_IO_RULES_HEALTH);
- log.error(msgFormat.format(new Object[] {groupTag.getId()}));
- }
- }
-
- /**
- * This method does the rule based dialog management based on the
- * navigational rules supplied
- */
- private void dialogManager(GroupTag groupTag) {
-
- GroupModel groupModel = (GroupModel) stateMap.get(groupTag.getId());
- Map children = groupModel.getLocalMap();
- if (children == null) {
- return;
- }
-
- List activeChildren = groupModel.getActiveChildren();
- String currentExec = null;
- NavigationRule navRule = null;
-
- if (activeChildren.size() == 0) {
- /*
- * SAMPLE XML navigation rule executed here:
- * <intial target="first-rdc-id" />
- */
- navRule = (NavigationRule) navigation.get(null);
- } else {
- // Only one child executes at a time in this strategy
- currentExec = (String) activeChildren.get(0);
- BaseModel model = (BaseModel) children.get(currentExec);
- if (!DMUtils.isChildDone(model)) {
- return;
- }
- navRule= (NavigationRule) navigation.get(currentExec);
- }
-
- if (navRule != null) {
-
- if (navRule.getConditions().size() == 0) {
- currentExec = navRule.getTarget();
- groupState = DMUtils.invokeDormantChild(children,
- activeChildren, currentExec);
- } else {
- List conditionals = navRule.getConditions();
- currentExec = identifyTarget(conditionals, groupTag,
- groupModel, lruCache, tempVars);
- if (activeChildren.size() > 0) {
- activeChildren.remove(0);
- }
- if (currentExec != null) {
- groupState = DMUtils.invokeDormantChild(children,
- activeChildren, currentExec);
- } else {
- currentExec = navRule.getDefaultTarget();
- if (currentExec != null) {
- groupState = DMUtils.invokeDormantChild(children,
- activeChildren, currentExec);
- } else {
- groupState = Constants.GRP_ALL_CHILDREN_DONE;
- log.info("RuleBasedDirectedDialog: None" +
- " of the conditions satisfied for " +
- (navRule.getFrom() == null ? "initial" : "") +
- " navigation rule " +
- (navRule.getFrom() != null ? "from: " +
- navRule.getFrom() : "") + " - finished execution" +
- " of group with ID " + groupTag.getId());
- }
- }
- }
-
- } else {
- // No navigation rule available, we're all done
- if (activeChildren.size() > 0) {
- activeChildren.remove(0);
- }
- groupState = Constants.GRP_ALL_CHILDREN_DONE;
- }
-
- } // end method dialogManager()
-
- /**
- * Render next child in execution order if:
- * a) The currently active child is done
- * and
- * b) The currently active child is not the last child
- * in the execution order
- */
- private static boolean renderNextChild(GroupModel groupModel) {
- Map children = groupModel.getLocalMap();
- List activeChildren = groupModel.getActiveChildren();
- // Only one child executes at a time in this strategy
- if (activeChildren.size() > 0) {
- BaseModel model = (BaseModel)children.get(activeChildren.get(0));
- if (DMUtils.isChildDone(model)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Evaluate the given list of Condition objects with respect
- * to the state of the given GroupModel.
- *
- * @param Condition
- */
- private static String identifyTarget(List conditions, GroupTag groupTag,
- GroupModel groupModel, LinkedHashMap lruCache, List tempVars) {
- String currentExec = null;
- boolean goodCondition = false;
- // Assumes navigation rules define a deterministic
- // state transition graph
- for (int i = 0; i < conditions.size() &&
- !goodCondition; i++) {
- Object condData = conditions.get(i);
- if (condData instanceof Condition) {
- Condition cond = (Condition) condData;
- cond.setExecutionContext(groupTag, groupModel, lruCache,
- tempVars);
- goodCondition = cond.isSatisfied();
- if (goodCondition) {
- currentExec = ((Condition) condData).getTarget();
- }
- } else {
- log.warn("List of conditionals contains instance of " +
- "unexpected class - " + condData.getClass().getName());
- }
- }
- cleanup(groupTag.getJspContext(), tempVars, lruCache);
- return currentExec;
- }
-
- /**
- * Remove all temporary attributes from this page context and clear
- * the cache
- *
- */
- private static void cleanup(JspContext ctx, List attributeList,
- LinkedHashMap cache) {
- for (int i = 0; i < attributeList.size(); i++) {
- ctx.removeAttribute((String)attributeList.get(i));
- }
- attributeList.clear();
- cache.clear();
- }
-
- /**
- * Obtains rules, which may be packed in the distribution jar
- */
- private static InputSource getRulesAsInputSource(final Digester digester,
- final JspContext ctx, final String rules)
- throws IOException {
- InputSource inputSrc = null;
- if (!RDCUtils.isStringEmpty(rules) && rules.startsWith("META-INF/")) {
- // unpack rules from distro, which we know validate
- if (digester != null) {
- digester.setValidating(false);
- }
- final String jar = ((PageContext)ctx).getServletContext().
- getRealPath(Constants.RDC_JAR);
- inputSrc = RDCUtils.extract(jar, rules);
- } else {
- if (digester != null) {
- digester.setValidating(true);
- }
- inputSrc = new InputSource(((PageContext)ctx).getServletContext().
- getRealPath(rules));
- }
- return inputSrc;
- }
-
- /**
- * Java Object encapsulating the XML navigation rules.
- *
- * Corresponds to the root <navigation> element in XML
- * navigation rules.
- */
- public static class Navigation {
-
- private Map navMap = null;
- // Following strings should not be XML NMTOKENs
- public static final String NAV_RULE_SET_CREATION = "<";
- public static final String NAV_SUCCESS = ">";
-
- public Navigation() {
- navMap = new HashMap();
- navMap.put(NAV_RULE_SET_CREATION, NAV_SUCCESS);
- }
-
- public Object get(String key) {
- return navMap.get(key);
- }
-
- // This is a directed dialog strategy where only one child
- // executes at a time.
- // It is expected that one unique target is specified by the XML
- // navigation rule set for any given state transition within
- // the group.
- public void addNavigationRule(NavigationRule navRule) {
- String key = navRule.getFrom();
- if (navMap.containsKey(key)) {
- navMap.put(NAV_RULE_SET_CREATION, key);
- }
- navMap.put(key, navRule);
- }
-
- }
-
- /**
- * Java Object corresponding to an individual XML navigation
- * rule defined in the XML navigation rules structure.
- *
- * Corresponds to <rule> element in XML navigation rules.
- */
- public static class NavigationRule {
-
- private String from;
- private String target;
- private String defaultTarget;
- private List conditions;
-
- public NavigationRule() {
- from = null;
- target = null;
- defaultTarget = null;
- conditions = new ArrayList();
- }
-
- public String getFrom() {
- return from;
- }
-
- public void setFrom(String from) {
- this.from = from.trim();
- }
-
- public String getTarget() {
- return target;
- }
-
- public void setTarget(String target) {
- this.target = target.trim();
- }
-
- public String getDefaultTarget() {
- return defaultTarget;
- }
-
- public void setDefaultTarget(String defaultTarget) {
- this.defaultTarget = defaultTarget.trim();
- }
-
- public List getConditions() {
- return conditions;
- }
-
- public void addCondition(Condition condition) {
- conditions.add(condition);
- }
-
- }
-
-
- /**
- * Condition interface
- *
- * Implementing classes must also define an accessible method
- * of the following signature: static Map getAttrPropMap()
- */
- public static interface Condition {
-
- public void setExecutionContext(GroupTag groupTag,
- GroupModel groupModel, LinkedHashMap lruCache,
- List tempVars);
-
- public boolean isSatisfied();
-
- public String getTarget();
-
- }
-
- /**
- * Java Object corresponding to an individual condition defined within a
- * rule in the XML navigation rules structure.
- *
- * Corresponds to <condition> element in XML navigation rules.
- */
- public static class ConditionImpl implements Condition {
-
- private static final Map opCodes = new HashMap();
- private static final Map lvalueTypes = new HashMap();
- private static final Map rvalueTypes = new HashMap();
- private static final int UNSUPPORTED_OPERATION = 873264831;
-
- static {
- opCodes.put("less-than", "-1");
- opCodes.put("equal-to", "0");
- opCodes.put("greater-than", "1");
- }
-
- protected String lvalue;
- protected String operation;
- protected String rvalue;
- protected String target;
- protected GroupTag groupTag;
- protected GroupModel groupModel;
- protected LinkedHashMap lruCache;
- protected List tempVars;
- protected boolean isExecCtxSet;
-
- public ConditionImpl() {
- lvalue = null;
- operation = null;
- rvalue = null;
- target = null;
- isExecCtxSet = false;
- }
-
- public void setExecutionContext(GroupTag groupTag,
- GroupModel groupModel, LinkedHashMap lruCache,
- List tempVars) {
- this.groupTag = groupTag;
- this.groupModel = groupModel;
- this.lruCache = lruCache;
- this.tempVars = tempVars;
- if (groupTag != null && groupModel != null) {
- isExecCtxSet = true;
- }
- }
-
- public static Map getAttrPropMap() {
- Map attrPropMap = new HashMap();
- attrPropMap.put("lvalue", "lvalue");
- attrPropMap.put("operation", "operation");
- attrPropMap.put("rvalue", "rvalue");
- attrPropMap.put("target", "target");
- return attrPropMap;
- }
-
- public String getLvalue() {
- return lvalue;
- }
-
- public String getRvalue() {
- return rvalue;
- }
-
- public String getOperation() {
- return operation;
- }
-
- public String getTarget() {
- return target;
- }
-
- public void setLvalue(String string) {
- lvalue = string;
- }
-
- public void setRvalue(String string) {
- rvalue = string;
- }
-
- public void setOperation(String operation) {
- this.operation = operation.trim();
- }
-
- public void setTarget(String target) {
- this.target = target.trim();
- }
-
- public int getOpCode() {
- int i = UNSUPPORTED_OPERATION;
- try {
- i = Integer.parseInt((String)opCodes.get(operation));
- } catch (NumberFormatException nfe) {
- // unsupported operation - do nothing
- }
- return i;
- }
-
- public static String getLvalueType(int opCode) {
- return (String)lvalueTypes.get("" + opCode);
- }
-
- public static String getRvalueType(int opCode) {
- return (String)rvalueTypes.get("" + opCode);
- }
-
- public void pre() {
- // pre hook for subclasses
- }
-
- public void post() {
- // post hook for subclasses
- }
-
- public boolean isSatisfied() {
-
- pre();
- int opCode = getOpCode();
- String lvalueClassName = getLvalueType(opCode);
- String rvalueClassName = getRvalueType(opCode);
- // operands are assumed to be strings by default
- Class lvalueClass = java.lang.String.class;
- Class rvalueClass = java.lang.String.class;
- if (!RDCUtils.isStringEmpty(lvalueClassName)) {
- lvalueClass = RDCUtils.getClass(lvalueClassName);
- }
- if (!RDCUtils.isStringEmpty(rvalueClassName)) {
- rvalueClass = RDCUtils.getClass(rvalueClassName);
- }
- RDCUtils.mustSatisfy(lvalueClass != null && rvalueClass != null,
- "RuleBasedDirectedDialog.ConditionImpl: " + getClass().
- getName()+" condition has an undefined lvalue or rvalue type");
- String lvalue_expr = getLvalue();
- RDCUtils.warnIf(RDCUtils.isStringEmpty(lvalue_expr),
- "RuleBasedDirectedDialog.ConditionImpl: " +
- getClass().getName() + " condition has a null expression");
- Object lvalue = DMUtils.proprietaryEval(groupTag, groupModel,
- lvalue_expr, lvalueClass, lruCache, tempVars);
- String rvalue_expr = getRvalue();
- RDCUtils.warnIf(RDCUtils.isStringEmpty(rvalue_expr),
- "RuleBasedDirectedDialog.ConditionImpl: " +
- getClass().getName() + " condition has a null expression");
- Object rvalue = DMUtils.proprietaryEval(groupTag, groupModel,
- rvalue_expr, rvalueClass, lruCache, tempVars);
- post();
-
- switch (opCode) {
- // 1) Currently only proof of concept string based comparison
- // operations are supported. User can define any number of
- // custom operations.
- // 2) Operations can be made to behave differently based on
- // lvalue and rvalue data types.
- // 3) This is essential since RDCs can return an instance of an
- // arbitrary Java class
- case 0:
- // equal-to
- if (lvalue instanceof String && rvalue instanceof String) {
- if (lvalue != null && ((String)lvalue).
- equals((String)rvalue)) {
- return true;
- } else {
- return false;
- }
- }
- return false;
- case -1:
- // less-than
- if (lvalue instanceof String && rvalue instanceof String) {
- if (lvalue != null && ((String)lvalue).
- compareTo((String)rvalue) < 0) {
- return true;
- } else {
- return false;
- }
- }
- return false;
- case 1:
- // greater-than
- if (lvalue instanceof String && rvalue instanceof String) {
- if (lvalue != null && ((String)lvalue).
- compareTo((String)rvalue) > 0) {
- return true;
- } else {
- return false;
- }
- }
- return false;
- default:
- return false;
- }
- }
- }
-
- /**
- * Custom error handler to communicate parsing errors in the
- * XML navigation rules to the client.
- */
- private class NavigationRulesErrorHandler implements ErrorHandler {
-
- private static final String MSG_PREFIX = "<!-- " +
- "RuleBasedDirectedDialog: XML navigation rules - ";
- private static final String MSG_POSTFIX = " Correct the XML " +
- " navigation rule set. -->\n";
-
- private static final String ERR_IO_EXP = "IOException while " +
- "handling parsing errors for group config file: \"{0}\"";
-
- private final String errMsg;
-
- NavigationRulesErrorHandler() {
- super();
- MessageFormat msgFormat = new MessageFormat(ERR_IO_EXP);
- errMsg = msgFormat.format(new Object[] {groupTag.getConfig()});
- }
-
- public void error(SAXParseException s) {
- try {
- ((PageContext) groupTag.getJspContext()).getOut().
- write(MSG_PREFIX + groupTag.getConfig() + " : Error - " +
- s.getMessage() + MSG_POSTFIX);
- } catch (IOException ioe) {
- log.warn(errMsg);
- }
- }
-
- public void fatalError(SAXParseException s) {
- try {
- ((PageContext) groupTag.getJspContext()).getOut().
- write(MSG_PREFIX + groupTag.getConfig() + " : Fatal Error - " +
- s.getMessage() + MSG_POSTFIX);
- } catch (IOException ioe) {
- log.warn(errMsg);
- }
- }
-
- public void warning(SAXParseException s) {
- try {
- ((PageContext) groupTag.getJspContext()).getOut().
- write(MSG_PREFIX + groupTag.getConfig() + " : Warning - " +
- s.getMessage() + MSG_POSTFIX);
- } catch (IOException ioe) {
- log.warn(errMsg);
- }
- }
- }
+
+ private static final String XPATH_NAVIGATION =
+ "*/navigation";
+ private static final String XPATH_CONDITION =
+ "/dm-config/ruleset-def/conditions-list/condition-def";
+
+ private Navigation navigation = null;
+
+ private LinkedHashMap lruCache = new LinkedHashMap();
+ private List tempVars = new ArrayList();
+
+ // Error messages (to be i18n'zed)
+ private static final String ERR_TRANS_EXP = "Transformer Exception " +
+ "while trying to evaluate XPath expression: \"{0}\", with error " +
+ "message \"{1}\"";
+ private static final String ERR_DIGESTER_FAIL = "<!-- Error parsing " +
+ "XML navigation rules for group: \"{0}\", with message: \"{1}\" -->\n";
+ private static final String ERR_NULL_RULES = "<!-- Error parsing XML " +
+ "navigation rules for group: \"{0}\" -->\n";
+ private static final String ERR_IO_NULL_RULES = "<!-- IOException while" +
+ " reporting null navigation rules for group with ID \"{0}\" -->\n";
+ private static final String ERR_IO_RULES_HEALTH = "<!-- IOException " +
+ "while reporting health of navigation rules for group with ID \"{0}\"" +
+ " -->\n";
+
+ // Logging
+ private static Log log = LogFactory.getLog(RuleBasedDirectedDialog.class);
+
+ /* Constructor */
+ public RuleBasedDirectedDialog() {
+ super();
+ }
+
+ public boolean initialize(JspContext ctx, JspFragment bodyFragment)
+ throws JspException, IOException {
+
+ boolean retVal = super.initialize(ctx, bodyFragment);
+
+ GroupModel groupModel = (GroupModel) stateMap.get(groupTag.getId());
+ if (groupModel.getInstanceData() != null) {
+ navigation = (Navigation) groupModel.getInstanceData();
+ return retVal;
+ }
+
+ Digester digester = new Digester();
+ digester.setErrorHandler(new NavigationRulesErrorHandler());
+
+ digester.addObjectCreate(XPATH_NAVIGATION, Navigation.class);
+ digester.addObjectCreate(XPATH_NAVIGATION + "/initial",
+ NavigationRule.class);
+ digester.addSetProperties(XPATH_NAVIGATION + "/initial",
+ new String[] {"target", "defaultTarget"},
+ new String[] {"target", "defaultTarget"});
+ digester.addObjectCreate(XPATH_NAVIGATION + "/initial/condition",
+ ConditionImpl.class);
+ digester.addSetProperties(XPATH_NAVIGATION + "/initial/condition",
+ new String[] {"lvalue", "operation", "rvalue", "target"},
+ new String[] {"lvalue", "operation", "rvalue", "target"});
+ digester.addSetNext(XPATH_NAVIGATION + "/initial/condition",
+ "addCondition" );
+ digester.addSetNext(XPATH_NAVIGATION + "/initial","addNavigationRule");
+
+ digester.addObjectCreate(XPATH_NAVIGATION + "/rule",
+ NavigationRule.class);
+ digester.addSetProperties(XPATH_NAVIGATION + "/rule",
+ new String[] {"from", "target", "defaultTarget"},
+ new String[] {"from", "target", "defaultTarget"});
+ digester.addObjectCreate(XPATH_NAVIGATION + "/rule/condition",
+ ConditionImpl.class);
+ digester.addSetProperties(XPATH_NAVIGATION + "/rule/condition",
+ new String[] {"lvalue", "operation", "rvalue", "target"},
+ new String[] {"lvalue", "operation", "rvalue", "target"});
+ digester.addSetNext(XPATH_NAVIGATION + "/rule/condition",
+ "addCondition");
+ digester.addSetNext(XPATH_NAVIGATION + "/rule", "addNavigationRule" );
+
+ DOMParser dp = new DOMParser();
+ final String rules = groupTag.getConfig();
+ InputSource is1 = getRulesAsInputSource(null, ctx, rules);
+ try {
+ dp.parse(is1);
+ } catch (SAXException sx) {
+ throw new IOException("Cannot parse the config: " +
+ groupTag.getConfig());
+ } // end of try-catch
+ Document d = dp.getDocument();
+ NodeList conditionsList = null;
+ try {
+ conditionsList = XPathAPI.selectNodeList(d.getDocumentElement(),
+ XPATH_CONDITION);
+ } catch (TransformerException t) {
+ MessageFormat msgFormat = new MessageFormat(ERR_TRANS_EXP);
+ String errMsg = msgFormat.format(new Object[] {XPATH_CONDITION,
+ t.getMessage()});
+ log.error(errMsg);
+ ((PageContext) ctx).getOut().write(errMsg);
+ }
+
+ if (conditionsList != null) {
+ Set conditionNames = new HashSet();
+ conditionNames.add("condition");
+ for (int i = 0; i < conditionsList.getLength(); i++) {
+ String name = name = ((Element)conditionsList.item(i)).
+ getAttribute("name");
+ RDCUtils.mustExist(name, "RuleBasedDirectedDialog: Cannot" +
+ " add condition with empty name");
+ RDCUtils.mustSatisfy(!conditionNames.contains(name),
+ "RuleBasedDirectedDialog: Cannot add condition with " +
+ "name \"" + name + "\" since a condition with that " +
+ "name is already defined.");
+ String impl = ((Element)conditionsList.item(i)).
+ getAttribute("impl");
+ RDCUtils.mustExist(impl, "RuleBasedDirectedDialog: Cannot" +
+ " add condition with empty impl");
+ Class implClass = RDCUtils.getClass(impl);
+ if (implClass == null) {
+ continue;
+ }
+ RDCUtils.mustSatisfy(RDCUtils.implementsInterface(implClass,
+ Condition.class), "RuleBasedDirectedDialog: Cannot" +
+ " add condition with name \"" + name + "\". Impl:" +
+ impl + " does not implement the RuleBasedDirectedDialog." +
+ "Condition interface.");
+ RDCUtils.mustSatisfy(RDCUtils.hasMethod(implClass,
+ "getAttrPropMap", null), "RuleBasedDirectedDialog: Cannot"+
+ " add condition with name \"" + name + "\" since" +
+ " the impl class " + impl + " does not define an" +
+ " accessible method \"static Map getAttrPropMap()\"");
+ Method m = null;
+ Map attrPropMap = null;
+ try {
+ m = implClass.getMethod("getAttrPropMap", null);
+ attrPropMap = (Map) m.invoke(null, null);
+ } catch (Exception e) {
+ RDCUtils.warnIf(true, "RuleBasedDirectedDialog: Could not" +
+ " invoke getAttrPropMap() method of class: " + impl);
+ continue;
+ }
+ Object[] keysArray = attrPropMap.keySet().toArray();
+ String[] attrs = new String[keysArray.length];
+ String[] props = new String[keysArray.length];
+ for (int j = 0; j < keysArray.length; j++) {
+ attrs[j] = (String) keysArray[j];
+ RDCUtils.mustExist(attrs[j], "RuleBasedDirectedDialog: " +
+ "Cannot add condition element with empty attribute");
+ props[j] = (String) attrPropMap.get(attrs[j]);
+ RDCUtils.mustExist(attrs[j], "RuleBasedDirectedDialog: " +
+ "Attribute " + attrs[j] + " of condition with name " +
+ name +" is not mapped to a property of class " + impl);
+ RDCUtils.mustSatisfy(RDCUtils.hasField(implClass, props[j]),
+ "RuleBasedDirectedDialog: Attribute " + attrs[j] +
+ " of condition with name " + name + " is mapped " +
+ "to a property " + props[j] + ", which does not " +
+ "exist in the impl class " + impl);
+ }
+ digester.addObjectCreate(XPATH_NAVIGATION + "/initial/" + name,
+ impl);
+ digester.addSetProperties(XPATH_NAVIGATION + "/initial/" +name,
+ attrs, props);
+ digester.addSetNext(XPATH_NAVIGATION + "/initial/" + name,
+ "addCondition");
+ digester.addObjectCreate(XPATH_NAVIGATION + "/rule/" + name,
+ impl);
+ digester.addSetProperties(XPATH_NAVIGATION + "/rule/" + name,
+ attrs, props);
+ digester.addSetNext(XPATH_NAVIGATION + "/rule/" + name,
+ "addCondition" );
+ conditionNames.add(name);
+ }
+ }
+
+ InputSource is2 = getRulesAsInputSource(digester, ctx, rules);
+ try {
+ navigation = (Navigation) digester.parse(is2);
+ } catch (Exception e) {
+ retVal = false;
+ MessageFormat msgFormat = new MessageFormat(ERR_DIGESTER_FAIL);
+ String errMsg = msgFormat.format(new Object[] {groupTag.
+ getConfig(), e.getMessage()});
+ log.error(errMsg);
+ ((PageContext) ctx).getOut().write(errMsg);
+ }
+ groupModel.setInstanceData(navigation);
+
+ return retVal;
+ }
+
+ /**
+ * Collect the required information from the user
+ *
+ *
+ */
+ public void collect(JspContext ctx, JspFragment bodyFragment)
+ throws JspException, IOException {
+
+ checkRuleSetStatus();
+
+ GroupModel groupModel = (GroupModel) stateMap.get(groupTag.getId());
+ Map modelMap = groupModel.getLocalMap();
+
+ if (modelMap.get(Constants.STR_INIT_ONLY_FLAG) == Boolean.TRUE) {
+ // Start off with all children in dormant state
+ setStateChildren(modelMap, Constants.FSM_DORMANT);
+ groupState = Constants.GRP_ALL_CHILDREN_DORMANT;
+ groupModel.setState(Constants.GRP_STATE_RUNNING);
+ modelMap.put(Constants.STR_INIT_ONLY_FLAG, Boolean.FALSE);
+ }
+
+ if (groupModel.getState() == Constants.GRP_STATE_RUNNING) {
+ do {
+ dialogManager(groupTag);
+ if (bodyFragment != null) {
+ bodyFragment.invoke(null);
+ }
+ } while (renderNextChild(groupModel));
+ }
+ }
+
+ /**
+ * Check the health of the navigation rule set, and provide
+ * client feedback for error conditions.
+ *
+ * @param navigation The Navigation rule set
+ */
+ private void checkRuleSetStatus() {
+
+ if (navigation == null) {
+ try {
+ MessageFormat msgFormat = new MessageFormat(ERR_NULL_RULES);
+ String errMsg = msgFormat.format(new Object[] {groupTag.
+ getConfig()});
+ log.error(errMsg);
+ ((PageContext) groupTag.getJspContext()).getOut().
+ write(errMsg);
+ } catch (IOException ioe) {
+ MessageFormat msgFormat = new MessageFormat(ERR_IO_NULL_RULES);
+ log.error(msgFormat.format(new Object[] {groupTag.getId()}));
+ }
+ return;
+ }
+
+ String navHealth = (String)navigation.get(Navigation.
+ NAV_RULE_SET_CREATION);
+ StringBuffer strbuf = new StringBuffer("<!--");
+ if (navHealth == null) {
+ strbuf.append("The initial navigation rule");
+ } else if (!navHealth.equals(Navigation.NAV_SUCCESS)) {
+ strbuf.append("The navigation rule originating from component " +
+ "with ID \"" + navHealth + "\"");
+ } else {
+ return;
+ }
+ strbuf.append(" has been overwritten. Correct the XML navigation " +
+ "rule set in " + groupTag.getConfig() + " -->\n");
+
+ try {
+ ((PageContext) groupTag.getJspContext()).getOut().
+ write(strbuf.toString());
+ } catch (IOException ioe) {
+ MessageFormat msgFormat = new MessageFormat(ERR_IO_RULES_HEALTH);
+ log.error(msgFormat.format(new Object[] {groupTag.getId()}));
+ }
+ }
+
+ /**
+ * This method does the rule based dialog management based on the
+ * navigational rules supplied
+ */
+ private void dialogManager(GroupTag groupTag) {
+
+ GroupModel groupModel = (GroupModel) stateMap.get(groupTag.getId());
+ Map children = groupModel.getLocalMap();
+ if (children == null) {
+ return;
+ }
+
+ List activeChildren = groupModel.getActiveChildren();
+ String currentExec = null;
+ NavigationRule navRule = null;
+
+ if (activeChildren.size() == 0) {
+ /*
+ * SAMPLE XML navigation rule executed here:
+ * <intial target="first-rdc-id" />
+ */
+ navRule = (NavigationRule) navigation.get(null);
+ } else {
+ // Only one child executes at a time in this strategy
+ currentExec = (String) activeChildren.get(0);
+ BaseModel model = (BaseModel) children.get(currentExec);
+ if (!DMUtils.isChildDone(model)) {
+ return;
+ }
+ navRule= (NavigationRule) navigation.get(currentExec);
+ }
+
+ if (navRule != null) {
+
+ if (navRule.getConditions().size() == 0) {
+ currentExec = navRule.getTarget();
+ groupState = DMUtils.invokeDormantChild(children,
+ activeChildren, currentExec);
+ } else {
+ List conditionals = navRule.getConditions();
+ currentExec = identifyTarget(conditionals, groupTag,
+ groupModel, lruCache, tempVars);
+ if (activeChildren.size() > 0) {
+ activeChildren.remove(0);
+ }
+ if (currentExec != null) {
+ groupState = DMUtils.invokeDormantChild(children,
+ activeChildren, currentExec);
+ } else {
+ currentExec = navRule.getDefaultTarget();
+ if (currentExec != null) {
+ groupState = DMUtils.invokeDormantChild(children,
+ activeChildren, currentExec);
+ } else {
+ groupState = Constants.GRP_ALL_CHILDREN_DONE;
+ log.info("RuleBasedDirectedDialog: None" +
+ " of the conditions satisfied for " +
+ (navRule.getFrom() == null ? "initial" : "") +
+ " navigation rule " +
+ (navRule.getFrom() != null ? "from: " +
+ navRule.getFrom() : "") + " - finished execution" +
+ " of group with ID " + groupTag.getId());
+ }
+ }
+ }
+
+ } else {
+ // No navigation rule available, we're all done
+ if (activeChildren.size() > 0) {
+ activeChildren.remove(0);
+ }
+ groupState = Constants.GRP_ALL_CHILDREN_DONE;
+ }
+
+ } // end method dialogManager()
+
+ /**
+ * Render next child in execution order if:
+ * a) The currently active child is done
+ * and
+ * b) The currently active child is not the last child
+ * in the execution order
+ */
+ private static boolean renderNextChild(GroupModel groupModel) {
+ Map children = groupModel.getLocalMap();
+ List activeChildren = groupModel.getActiveChildren();
+ // Only one child executes at a time in this strategy
+ if (activeChildren.size() > 0) {
+ BaseModel model = (BaseModel)children.get(activeChildren.get(0));
+ if (DMUtils.isChildDone(model)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Evaluate the given list of Condition objects with respect
+ * to the state of the given GroupModel.
+ *
+ * @param Condition
+ */
+ private static String identifyTarget(List conditions, GroupTag groupTag,
+ GroupModel groupModel, LinkedHashMap lruCache, List tempVars) {
+ String currentExec = null;
+ boolean goodCondition = false;
+ // Assumes navigation rules define a deterministic
+ // state transition graph
+ for (int i = 0; i < conditions.size() &&
+ !goodCondition; i++) {
+ Object condData = conditions.get(i);
+ if (condData instanceof Condition) {
+ Condition cond = (Condition) condData;
+ cond.setExecutionContext(groupTag, groupModel, lruCache,
+ tempVars);
+ goodCondition = cond.isSatisfied();
+ if (goodCondition) {
+ currentExec = ((Condition) condData).getTarget();
+ }
+ } else {
+ log.warn("List of conditionals contains instance of " +
+ "unexpected class - " + condData.getClass().getName());
+ }
+ }
+ cleanup(groupTag.getJspContext(), tempVars, lruCache);
+ return currentExec;
+ }
+
+ /**
+ * Remove all temporary attributes from this page context and clear
+ * the cache
+ *
+ */
+ private static void cleanup(JspContext ctx, List attributeList,
+ LinkedHashMap cache) {
+ for (int i = 0; i < attributeList.size(); i++) {
+ ctx.removeAttribute((String)attributeList.get(i));
+ }
+ attributeList.clear();
+ cache.clear();
+ }
+
+ /**
+ * Obtains rules, which may be packed in the distribution jar
+ */
+ private static InputSource getRulesAsInputSource(final Digester digester,
+ final JspContext ctx, final String rules)
+ throws IOException {
+ InputSource inputSrc = null;
+ if (!RDCUtils.isStringEmpty(rules) && rules.startsWith("META-INF/")) {
+ // unpack rules from distro, which we know validate
+ if (digester != null) {
+ digester.setValidating(false);
+ }
+ final String jar = ((PageContext)ctx).getServletContext().
+ getRealPath(Constants.RDC_JAR);
+ inputSrc = RDCUtils.extract(jar, rules);
+ } else {
+ if (digester != null) {
+ digester.setValidating(true);
+ }
+ inputSrc = new InputSource(((PageContext)ctx).getServletContext().
+ getRealPath(rules));
+ }
+ return inputSrc;
+ }
+
+ /**
+ * Java Object encapsulating the XML navigation rules.
+ *
+ * Corresponds to the root <navigation> element in XML
+ * navigation rules.
+ */
+ public static class Navigation {
+
+ private Map navMap = null;
+ // Following strings should not be XML NMTOKENs
+ public static final String NAV_RULE_SET_CREATION = "<";
+ public static final String NAV_SUCCESS = ">";
+
+ public Navigation() {
+ navMap = new HashMap();
+ navMap.put(NAV_RULE_SET_CREATION, NAV_SUCCESS);
+ }
+
+ public Object get(String key) {
+ return navMap.get(key);
+ }
+
+ // This is a directed dialog strategy where only one child
+ // executes at a time.
+ // It is expected that one unique target is specified by the XML
+ // navigation rule set for any given state transition within
+ // the group.
+ public void addNavigationRule(NavigationRule navRule) {
+ String key = navRule.getFrom();
+ if (navMap.containsKey(key)) {
+ navMap.put(NAV_RULE_SET_CREATION, key);
+ }
+ navMap.put(key, navRule);
+ }
+
+ }
+
+ /**
+ * Java Object corresponding to an individual XML navigation
+ * rule defined in the XML navigation rules structure.
+ *
+ * Corresponds to <rule> element in XML navigation rules.
+ */
+ public static class NavigationRule {
+
+ private String from;
+ private String target;
+ private String defaultTarget;
+ private List conditions;
+
+ public NavigationRule() {
+ from = null;
+ target = null;
+ defaultTarget = null;
+ conditions = new ArrayList();
+ }
+
+ public String getFrom() {
+ return from;
+ }
+
+ public void setFrom(String from) {
+ this.from = from.trim();
+ }
+
+ public String getTarget() {
+ return target;
+ }
+
+ public void setTarget(String target) {
+ this.target = target.trim();
+ }
+
+ public String getDefaultTarget() {
+ return defaultTarget;
+ }
+
+ public void setDefaultTarget(String defaultTarget) {
+ this.defaultTarget = defaultTarget.trim();
+ }
+
+ public List getConditions() {
+ return conditions;
+ }
+
+ public void addCondition(Condition condition) {
+ conditions.add(condition);
+ }
+
+ }
+
+
+ /**
+ * Condition interface
+ *
+ * Implementing classes must also define an accessible method
+ * of the following signature: static Map getAttrPropMap()
+ */
+ public static interface Condition {
+
+ public void setExecutionContext(GroupTag groupTag,
+ GroupModel groupModel, LinkedHashMap lruCache,
+ List tempVars);
+
+ public boolean isSatisfied();
+
+ public String getTarget();
+
+ }
+
+ /**
+ * Java Object corresponding to an individual condition defined within a
+ * rule in the XML navigation rules structure.
+ *
+ * Corresponds to <condition> element in XML navigation rules.
+ */
+ public static class ConditionImpl implements Condition {
+
+ private static final Map opCodes = new HashMap();
+ private static final Map lvalueTypes = new HashMap();
+ private static final Map rvalueTypes = new HashMap();
+ private static final int UNSUPPORTED_OPERATION = 873264831;
+
+ static {
+ opCodes.put("less-than", "-1");
+ opCodes.put("equal-to", "0");
+ opCodes.put("greater-than", "1");
+ }
+
+ protected String lvalue;
+ protected String operation;
+ protected String rvalue;
+ protected String target;
+ protected GroupTag groupTag;
+ protected GroupModel groupModel;
+ protected LinkedHashMap lruCache;
+ protected List tempVars;
+ protected boolean isExecCtxSet;
+
+ public ConditionImpl() {
+ lvalue = null;
+ operation = null;
+ rvalue = null;
+ target = null;
+ isExecCtxSet = false;
+ }
+
+ public void setExecutionContext(GroupTag groupTag,
+ GroupModel groupModel, LinkedHashMap lruCache,
+ List tempVars) {
+ this.groupTag = groupTag;
+ this.groupModel = groupModel;
+ this.lruCache = lruCache;
+ this.tempVars = tempVars;
+ if (groupTag != null && groupModel != null) {
+ isExecCtxSet = true;
+ }
+ }
+
+ public static Map getAttrPropMap() {
+ Map attrPropMap = new HashMap();
+ attrPropMap.put("lvalue", "lvalue");
+ attrPropMap.put("operation", "operation");
+ attrPropMap.put("rvalue", "rvalue");
+ attrPropMap.put("target", "target");
+ return attrPropMap;
+ }
+
+ public String getLvalue() {
+ return lvalue;
+ }
+
+ public String getRvalue() {
+ return rvalue;
+ }
+
+ public String getOperation() {
+ return operation;
+ }
+
+ public String getTarget() {
+ return target;
+ }
+
+ public void setLvalue(String string) {
+ lvalue = string;
+ }
+
+ public void setRvalue(String string) {
+ rvalue = string;
+ }
+
+ public void setOperation(String operation) {
+ this.operation = operation.trim();
+ }
+
+ public void setTarget(String target) {
+ this.target = target.trim();
+ }
+
+ public int getOpCode() {
+ int i = UNSUPPORTED_OPERATION;
+ try {
+ i = Integer.parseInt((String)opCodes.get(operation));
+ } catch (NumberFormatException nfe) {
+ // unsupported operation - do nothing
+ }
+ return i;
+ }
+
+ public static String getLvalueType(int opCode) {
+ return (String)lvalueTypes.get("" + opCode);
+ }
+
+ public static String getRvalueType(int opCode) {
+ return (String)rvalueTypes.get("" + opCode);
+ }
+
+ public void pre() {
+ // pre hook for subclasses
+ }
+
+ public void post() {
+ // post hook for subclasses
+ }
+
+ public boolean isSatisfied() {
+
+ pre();
+ int opCode = getOpCode();
+ String lvalueClassName = getLvalueType(opCode);
+ String rvalueClassName = getRvalueType(opCode);
+ // operands are assumed to be strings by default
+ Class lvalueClass = java.lang.String.class;
+ Class rvalueClass = java.lang.String.class;
+ if (!RDCUtils.isStringEmpty(lvalueClassName)) {
+ lvalueClass = RDCUtils.getClass(lvalueClassName);
+ }
+ if (!RDCUtils.isStringEmpty(rvalueClassName)) {
+ rvalueClass = RDCUtils.getClass(rvalueClassName);
+ }
+ RDCUtils.mustSatisfy(lvalueClass != null && rvalueClass != null,
+ "RuleBasedDirectedDialog.ConditionImpl: " + getClass().
+ getName()+" condition has an undefined lvalue or rvalue type");
+ String lvalue_expr = getLvalue();
+ RDCUtils.warnIf(RDCUtils.isStringEmpty(lvalue_expr),
+ "RuleBasedDirectedDialog.ConditionImpl: " +
+ getClass().getName() + " condition has a null expression");
+ Object lvalue = DMUtils.proprietaryEval(groupTag, groupModel,
+ lvalue_expr, lvalueClass, lruCache, tempVars);
+ String rvalue_expr = getRvalue();
+ RDCUtils.warnIf(RDCUtils.isStringEmpty(rvalue_expr),
+ "RuleBasedDirectedDialog.ConditionImpl: " +
+ getClass().getName() + " condition has a null expression");
+ Object rvalue = DMUtils.proprietaryEval(groupTag, groupModel,
+ rvalue_expr, rvalueClass, lruCache, tempVars);
+ post();
+
+ switch (opCode) {
+ // 1) Currently only proof of concept string based comparison
+ // operations are supported. User can define any number of
+ // custom operations.
+ // 2) Operations can be made to behave differently based on
+ // lvalue and rvalue data types.
+ // 3) This is essential since RDCs can return an instance of an
+ // arbitrary Java class
+ case 0:
+ // equal-to
+ if (lvalue instanceof String && rvalue instanceof String) {
+ if (lvalue != null && ((String)lvalue).
+ equals((String)rvalue)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return false;
+ case -1:
+ // less-than
+ if (lvalue instanceof String && rvalue instanceof String) {
+ if (lvalue != null && ((String)lvalue).
+ compareTo((String)rvalue) < 0) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return false;
+ case 1:
+ // greater-than
+ if (lvalue instanceof String && rvalue instanceof String) {
+ if (lvalue != null && ((String)lvalue).
+ compareTo((String)rvalue) > 0) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return false;
+ default:
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Custom error handler to communicate parsing errors in the
+ * XML navigation rules to the client.
+ */
+ private class NavigationRulesErrorHandler implements ErrorHandler {
+
+ private static final String MSG_PREFIX = "<!-- " +
+ "RuleBasedDirectedDialog: XML navigation rules - ";
+ private static final String MSG_POSTFIX = " Correct the XML " +
+ " navigation rule set. -->\n";
+
+ private static final String ERR_IO_EXP = "IOException while " +
+ "handling parsing errors for group config file: \"{0}\"";
+
+ private final String errMsg;
+
+ NavigationRulesErrorHandler() {
+ super();
+ MessageFormat msgFormat = new MessageFormat(ERR_IO_EXP);
+ errMsg = msgFormat.format(new Object[] {groupTag.getConfig()});
+ }
+
+ public void error(SAXParseException s) {
+ try {
+ ((PageContext) groupTag.getJspContext()).getOut().
+ write(MSG_PREFIX + groupTag.getConfig() + " : Error - " +
+ s.getMessage() + MSG_POSTFIX);
+ } catch (IOException ioe) {
+ log.warn(errMsg);
+ }
+ }
+
+ public void fatalError(SAXParseException s) {
+ try {
+ ((PageContext) groupTag.getJspContext()).getOut().
+ write(MSG_PREFIX + groupTag.getConfig() + " : Fatal Error - " +
+ s.getMessage() + MSG_POSTFIX);
+ } catch (IOException ioe) {
+ log.warn(errMsg);
+ }
+ }
+
+ public void warning(SAXParseException s) {
+ try {
+ ((PageContext) groupTag.getJspContext()).getOut().
+ write(MSG_PREFIX + groupTag.getConfig() + " : Warning - " +
+ s.getMessage() + MSG_POSTFIX);
+ } catch (IOException ioe) {
+ log.warn(errMsg);
+ }
+ }
+ }
}
Modified: jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/dm/SCXMLDialog.java
URL: http://svn.apache.org/viewcvs/jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/dm/SCXMLDialog.java?rev=231329&r1=231328&r2=231329&view=diff
==============================================================================
--- jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/dm/SCXMLDialog.java (original)
+++ jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/dm/SCXMLDialog.java Wed Aug 10 14:10:59 2005
@@ -74,236 +74,236 @@
* @author Jaroslav Gergic
*/
public class SCXMLDialog extends DialogManagerImpl {
-
- private static final String ERR_DIGESTER_FAIL = "<!-- Error parsing " +
- "SCXML document for group: \"{0}\", with message: \"{1}\" -->\n";
-
- // Logging
- private static Log log = LogFactory.getLog(SCXMLDialog.class);
-
- /**
- * The SCXML engine that will execute the SCXML document specified
- * in the group configuration.
- */
- private SCXMLExecutor exec;
-
- public SCXMLDialog() {
- super();
- }
-
- public boolean initialize(JspContext ctx, JspFragment bodyFragment)
- throws JspException, IOException {
-
- boolean retVal = super.initialize(ctx, bodyFragment);
- GroupModel groupModel = (GroupModel) stateMap.get(groupTag.getId());
-
- if (groupModel.getInstanceData() != null) {
- exec = (SCXMLExecutor) groupModel.getInstanceData();
- return retVal;
- }
-
- SCXML scxml = null;
- Evaluator engine = new ELEvaluator();
- Context rootCtx = new RootContext(ctx);
- ServletContext sc = ((PageContext) ctx).getServletContext();
- try {
- scxml = SCXMLDigester.digest(sc.getRealPath(groupTag.getConfig()),
- new SCXMLErrorHandler(), rootCtx, engine,
- new ServletContextResolver(sc));
- } catch (Exception e) {
- MessageFormat msgFormat = new MessageFormat(ERR_DIGESTER_FAIL);
- String errMsg = msgFormat.format(new Object[] {groupTag.
- getConfig(), e.getMessage()});
- log.error(errMsg, e);
- ((PageContext) ctx).getOut().write(errMsg);
- }
-
- if (scxml == null) {
- retVal = false;
- ((PageContext) ctx).getOut().write("<!-- SCXMLDialog" +
- ": Error parsing SCXML:" + groupTag.getConfig()+
- "-->\n");
- } else {
- // TODO - Remove debugging statement and else above
- //System.out.println(SCXMLDigester.serializeSCXML(scxml));
- }
-
- EventDispatcher ed = new SimpleDispatcher();
- Tracer trc = new Tracer();
- try {
- exec = new SCXMLExecutor(engine, ed, trc);
- scxml.addListener(trc);
- exec.setSuperStep(true);
- exec.setStateMachine(scxml);
- } catch (ModelException me) {
- retVal = false;
- ((PageContext) ctx).getOut().write("<!-- SCXMLDialog" +
- ": Model Exception in:" + groupTag.getConfig()+
- ", root cause: " + me.getMessage() + "-->\n");
- }
- groupModel.setInstanceData(exec);
-
- return retVal;
- }
-
- /**
- * Collect the required information based on the SCXML config
- */
- public void collect(JspContext ctx, JspFragment bodyFragment)
- throws JspException, IOException {
-
- GroupModel groupModel = (GroupModel) stateMap.get(groupTag.getId());
- Map modelMap = groupModel.getLocalMap();
-
- if (modelMap.get(Constants.STR_INIT_ONLY_FLAG) == Boolean.TRUE) {
- // Start off with all children in dormant state
- setStateChildren(modelMap, Constants.FSM_DORMANT);
- groupState = Constants.GRP_ALL_CHILDREN_DORMANT;
- groupModel.setState(Constants.GRP_STATE_RUNNING);
- modelMap.put(Constants.STR_INIT_ONLY_FLAG, Boolean.FALSE);
- }
-
- if (groupModel.getState() == Constants.GRP_STATE_RUNNING) {
- Status s;
- do {
- s = exec.getCurrentStatus();
- dialogManager(groupTag);
- if (bodyFragment != null) {
- bodyFragment.invoke(null);
- }
- } while (renderNext(groupModel, s));
- }
- }
-
-
- /**
- * This method does the rule based dialog management based on the
- * navigational rules supplied
- */
- private void dialogManager(GroupTag groupTag) {
-
- GroupModel groupModel = (GroupModel) stateMap.get(groupTag.getId());
- Map children = groupModel.getLocalMap();
- if (children == null) {
- return;
- }
-
- List activeChildren = groupModel.getActiveChildren();
- List eventList = new ArrayList();
- Set currentStates = exec.getCurrentStatus().getStates();
- if (currentStates != null && currentStates.size() > 0) {
- Iterator iter = currentStates.iterator();
- while (iter.hasNext()) {
- String id = ((State) iter.next()).getId();
- BaseModel model = (BaseModel) children.get(id);
- groupState = DMUtils.invokeDormantChild(children,
- activeChildren, id);
- if (!DMUtils.isChildDone(model)) {
- continue;
- } else {
- activeChildren.remove(model.getId());
- eventList.add(model.getId() + ".done");
- }
- }
- } else {
- if (activeChildren.size() > 0) {
- activeChildren.clear();
- }
- groupState = Constants.GRP_ALL_CHILDREN_DONE;
- return;
- }
-
- if (eventList.size() == 0) {
- return;
- } else {
- //fire events one at a time
- for (int i = 0; i < eventList.size(); i++) {
- TriggerEvent evts[] = new TriggerEvent[] {
- new TriggerEvent((String) eventList.get(i),
- TriggerEvent.SIGNAL_EVENT, null) };
- log.trace("Triggering event " + eventList.get(i));
- try {
- exec.triggerEvents(evts);
- } catch (ModelException me) {
- log.error(me.getMessage(), me);
- }
- }
- }
-
- } // end method dialogManager()
-
- /**
- * Render new states due to events triggered in last dialogManager()
- * invocation if:
- * a) All currently active child are done
- * and
- * b) The current executor status reached is not final
- */
- private boolean renderNext(GroupModel groupModel, Status s) {
- Map children = groupModel.getLocalMap();
- List activeChildren = groupModel.getActiveChildren();
- int sz = activeChildren.size();
- if (sz > 0) {
- for (int i = 0; i < sz; i++) {
- BaseModel model = (BaseModel)children.
- get(activeChildren.get(i));
- if (!DMUtils.isChildDone(model)) {
- return false;
- }
- }
- } else {
- if (s.isFinal()) {
- if (activeChildren.size() > 0) {
- activeChildren.clear();
- }
- groupState = Constants.GRP_ALL_CHILDREN_DONE;
- log.info("A final configuration reached");
- return false;
- }
- }
- return true;
- }
-
- /**
- * Custom error handler to communicate parsing errors in the
- * XML navigation rules to the client.
- */
- private class SCXMLErrorHandler implements ErrorHandler {
-
- private static final String MSG_PREFIX = "<!-- " +
- "SCXMLDialog :";
- private static final String MSG_POSTFIX = " Correct the SCXML. " +
- "-->\n";
-
- public void error(SAXParseException s) {
- try {
- ((PageContext) groupTag.getJspContext()).getOut().
- write(MSG_PREFIX + groupTag.getConfig() + " Error - " +
- s.getMessage() + MSG_POSTFIX);
- } catch (IOException ioe) {
- ioe.printStackTrace();
- }
- }
-
- public void fatalError(SAXParseException s) {
- try {
- ((PageContext) groupTag.getJspContext()).getOut().
- write(MSG_PREFIX + groupTag.getConfig() + " Fatal Error - " +
- s.getMessage() + MSG_POSTFIX);
- } catch (IOException ioe) {
- ioe.printStackTrace();
- }
- }
-
- public void warning(SAXParseException s) {
- try {
- ((PageContext) groupTag.getJspContext()).getOut().
- write(MSG_PREFIX + groupTag.getConfig() + " Warning - " +
- s.getMessage() + MSG_POSTFIX);
- } catch (IOException ioe) {
- ioe.printStackTrace();
- }
- }
- }
-
+
+ private static final String ERR_DIGESTER_FAIL = "<!-- Error parsing " +
+ "SCXML document for group: \"{0}\", with message: \"{1}\" -->\n";
+
+ // Logging
+ private static Log log = LogFactory.getLog(SCXMLDialog.class);
+
+ /**
+ * The SCXML engine that will execute the SCXML document specified
+ * in the group configuration.
+ */
+ private SCXMLExecutor exec;
+
+ public SCXMLDialog() {
+ super();
+ }
+
+ public boolean initialize(JspContext ctx, JspFragment bodyFragment)
+ throws JspException, IOException {
+
+ boolean retVal = super.initialize(ctx, bodyFragment);
+ GroupModel groupModel = (GroupModel) stateMap.get(groupTag.getId());
+
+ if (groupModel.getInstanceData() != null) {
+ exec = (SCXMLExecutor) groupModel.getInstanceData();
+ return retVal;
+ }
+
+ SCXML scxml = null;
+ Evaluator engine = new ELEvaluator();
+ Context rootCtx = new RootContext(ctx);
+ ServletContext sc = ((PageContext) ctx).getServletContext();
+ try {
+ scxml = SCXMLDigester.digest(sc.getRealPath(groupTag.getConfig()),
+ new SCXMLErrorHandler(), rootCtx, engine,
+ new ServletContextResolver(sc));
+ } catch (Exception e) {
+ MessageFormat msgFormat = new MessageFormat(ERR_DIGESTER_FAIL);
+ String errMsg = msgFormat.format(new Object[] {groupTag.
+ getConfig(), e.getMessage()});
+ log.error(errMsg, e);
+ ((PageContext) ctx).getOut().write(errMsg);
+ }
+
+ if (scxml == null) {
+ retVal = false;
+ ((PageContext) ctx).getOut().write("<!-- SCXMLDialog" +
+ ": Error parsing SCXML:" + groupTag.getConfig()+
+ "-->\n");
+ } else {
+ // TODO - Remove debugging statement and else above
+ //System.out.println(SCXMLDigester.serializeSCXML(scxml));
+ }
+
+ EventDispatcher ed = new SimpleDispatcher();
+ Tracer trc = new Tracer();
+ try {
+ exec = new SCXMLExecutor(engine, ed, trc);
+ scxml.addListener(trc);
+ exec.setSuperStep(true);
+ exec.setStateMachine(scxml);
+ } catch (ModelException me) {
+ retVal = false;
+ ((PageContext) ctx).getOut().write("<!-- SCXMLDialog" +
+ ": Model Exception in:" + groupTag.getConfig()+
+ ", root cause: " + me.getMessage() + "-->\n");
+ }
+ groupModel.setInstanceData(exec);
+
+ return retVal;
+ }
+
+ /**
+ * Collect the required information based on the SCXML config
+ */
+ public void collect(JspContext ctx, JspFragment bodyFragment)
+ throws JspException, IOException {
+
+ GroupModel groupModel = (GroupModel) stateMap.get(groupTag.getId());
+ Map modelMap = groupModel.getLocalMap();
+
+ if (modelMap.get(Constants.STR_INIT_ONLY_FLAG) == Boolean.TRUE) {
+ // Start off with all children in dormant state
+ setStateChildren(modelMap, Constants.FSM_DORMANT);
+ groupState = Constants.GRP_ALL_CHILDREN_DORMANT;
+ groupModel.setState(Constants.GRP_STATE_RUNNING);
+ modelMap.put(Constants.STR_INIT_ONLY_FLAG, Boolean.FALSE);
+ }
+
+ if (groupModel.getState() == Constants.GRP_STATE_RUNNING) {
+ Status s;
+ do {
+ s = exec.getCurrentStatus();
+ dialogManager(groupTag);
+ if (bodyFragment != null) {
+ bodyFragment.invoke(null);
+ }
+ } while (renderNext(groupModel, s));
+ }
+ }
+
+
+ /**
+ * This method does the rule based dialog management based on the
+ * navigational rules supplied
+ */
+ private void dialogManager(GroupTag groupTag) {
+
+ GroupModel groupModel = (GroupModel) stateMap.get(groupTag.getId());
+ Map children = groupModel.getLocalMap();
+ if (children == null) {
+ return;
+ }
+
+ List activeChildren = groupModel.getActiveChildren();
+ List eventList = new ArrayList();
+ Set currentStates = exec.getCurrentStatus().getStates();
+ if (currentStates != null && currentStates.size() > 0) {
+ Iterator iter = currentStates.iterator();
+ while (iter.hasNext()) {
+ String id = ((State) iter.next()).getId();
+ BaseModel model = (BaseModel) children.get(id);
+ groupState = DMUtils.invokeDormantChild(children,
+ activeChildren, id);
+ if (!DMUtils.isChildDone(model)) {
+ continue;
+ } else {
+ activeChildren.remove(model.getId());
+ eventList.add(model.getId() + ".done");
+ }
+ }
+ } else {
+ if (activeChildren.size() > 0) {
+ activeChildren.clear();
+ }
+ groupState = Constants.GRP_ALL_CHILDREN_DONE;
+ return;
+ }
+
+ if (eventList.size() == 0) {
+ return;
+ } else {
+ //fire events one at a time
+ for (int i = 0; i < eventList.size(); i++) {
+ TriggerEvent evts[] = new TriggerEvent[] {
+ new TriggerEvent((String) eventList.get(i),
+ TriggerEvent.SIGNAL_EVENT, null) };
+ log.trace("Triggering event " + eventList.get(i));
+ try {
+ exec.triggerEvents(evts);
+ } catch (ModelException me) {
+ log.error(me.getMessage(), me);
+ }
+ }
+ }
+
+ } // end method dialogManager()
+
+ /**
+ * Render new states due to events triggered in last dialogManager()
+ * invocation if:
+ * a) All currently active child are done
+ * and
+ * b) The current executor status reached is not final
+ */
+ private boolean renderNext(GroupModel groupModel, Status s) {
+ Map children = groupModel.getLocalMap();
+ List activeChildren = groupModel.getActiveChildren();
+ int sz = activeChildren.size();
+ if (sz > 0) {
+ for (int i = 0; i < sz; i++) {
+ BaseModel model = (BaseModel)children.
+ get(activeChildren.get(i));
+ if (!DMUtils.isChildDone(model)) {
+ return false;
+ }
+ }
+ } else {
+ if (s.isFinal()) {
+ if (activeChildren.size() > 0) {
+ activeChildren.clear();
+ }
+ groupState = Constants.GRP_ALL_CHILDREN_DONE;
+ log.info("A final configuration reached");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Custom error handler to communicate parsing errors in the
+ * XML navigation rules to the client.
+ */
+ private class SCXMLErrorHandler implements ErrorHandler {
+
+ private static final String MSG_PREFIX = "<!-- " +
+ "SCXMLDialog :";
+ private static final String MSG_POSTFIX = " Correct the SCXML. " +
+ "-->\n";
+
+ public void error(SAXParseException s) {
+ try {
+ ((PageContext) groupTag.getJspContext()).getOut().
+ write(MSG_PREFIX + groupTag.getConfig() + " Error - " +
+ s.getMessage() + MSG_POSTFIX);
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ }
+ }
+
+ public void fatalError(SAXParseException s) {
+ try {
+ ((PageContext) groupTag.getJspContext()).getOut().
+ write(MSG_PREFIX + groupTag.getConfig() + " Fatal Error - " +
+ s.getMessage() + MSG_POSTFIX);
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ }
+ }
+
+ public void warning(SAXParseException s) {
+ try {
+ ((PageContext) groupTag.getJspContext()).getOut().
+ write(MSG_PREFIX + groupTag.getConfig() + " Warning - " +
+ s.getMessage() + MSG_POSTFIX);
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ }
+ }
+ }
+
}
Modified: jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/dm/SimpleDirectedDialog.java
URL: http://svn.apache.org/viewcvs/jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/dm/SimpleDirectedDialog.java?rev=231329&r1=231328&r2=231329&view=diff
==============================================================================
--- jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/dm/SimpleDirectedDialog.java (original)
+++ jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/dm/SimpleDirectedDialog.java Wed Aug 10 14:10:59 2005
@@ -39,143 +39,143 @@
*/
public class SimpleDirectedDialog extends DialogManagerImpl {
- /* Constructor */
- public SimpleDirectedDialog() {
- super();
- }
-
- /**
- * Collect the required information from the user
- *
- *
- */
- public void collect(JspContext ctx, JspFragment bodyFragment)
- throws JspException, IOException {
-
- GroupModel groupModel = (GroupModel) stateMap.get(groupTag.getId());
- Map modelMap = groupModel.getLocalMap();
-
- if (modelMap.get(Constants.STR_INIT_ONLY_FLAG) == Boolean.TRUE) {
- // DD starts off with all children in dormant state
- setStateChildren(modelMap, Constants.FSM_DORMANT);
- groupState = Constants.GRP_ALL_CHILDREN_DORMANT;
- groupModel.setState(Constants.GRP_STATE_RUNNING);
- modelMap.put(Constants.STR_INIT_ONLY_FLAG, Boolean.FALSE);
- } else {
- groupState = getGroupState(groupModel);
- }
-
- // Real work at the component level is done here
- if (groupModel.getState() == Constants.GRP_STATE_RUNNING) {
- do {
- dialogManagerDD(groupModel);
- if (bodyFragment != null) {
- bodyFragment.invoke(null);
- }
- } while ((groupState = getGroupState(groupModel)) ==
- Constants.GRP_SOME_CHILD_DORMANT);
- }
- }
-
-
- /**
- * This method does the directive dialog management and sets the state
- * to begin if they are in dormant state
- *
- * @param children Map that holds the id's
- */
- private void dialogManagerDD(GroupModel groupModel) {
-
- Map children = groupModel.getLocalMap();
- if (children == null) {
- return;
- }
-
- Iterator iter = children.keySet().iterator();
- String currentItem = null;
- int currentState;
- BaseModel model = null;
-
- while (iter.hasNext()) {
- currentItem = (String) iter.next();
- if (currentItem.equals(Constants.STR_INIT_ONLY_FLAG)) {
- continue;
- }
-
- model = (BaseModel) children.get(currentItem);
- currentState = model.getState();
- List activeChildren = groupModel.getActiveChildren();
-
- if (currentState != Constants.FSM_DONE &&
- currentState != Constants.GRP_STATE_DONE){
- // If the state is FSM_DORMANT, set it to FSM_INPUT
- if (currentState == Constants.FSM_DORMANT) {
- if (activeChildren.size() > 0) {
- activeChildren.remove(0);
- }
- activeChildren.add(model.getId());
- if (model instanceof GroupModel) {
- model.setState(Constants.GRP_STATE_RUNNING);
- } else {
- model.setState(Constants.FSM_INPUT);
- }
- }
- // Else, let child execute till completion
- return;
- }
- // If state is done, move on to next child
- } // end while iterate over Map children
-
- } // end method dialogManagerDD()
-
- /**
- * Returns the group state based on state of its children
- *
- * One of these states will be returned
- * GRP_SOME_CHILD_RUNNING -> either of the children are in the execution
- * phase, if the children are not done they are in running state
- *
- * GRP_SOME_CHILD_DORMANT -> either of the children are in input state
- * could be say "done->input->input"
- *
- * GRP_ALL_CHILDREN_DONE -> if the child list is empty or if all the
- * children are done say "done->done->done"
- *
- * @param children Map that holds the id's
- * @return the child state
- */
- private int getGroupState(GroupModel groupModel) {
- Map children = groupModel.getLocalMap();
- if (children == null) {
- return Constants.GRP_ALL_CHILDREN_DONE;
- }
-
- Iterator iter = children.keySet().iterator();
- String current;
- int childState;
-
- //Loop while there are elements in the list
- while (iter.hasNext()) {
- current = (String) iter.next();
- if (current.equals(Constants.STR_INIT_ONLY_FLAG)) {
- continue;
- }
-
- childState = ((BaseModel) children.get(current)).getState();
-
- if (childState == Constants.FSM_DORMANT) {
- return Constants.GRP_SOME_CHILD_DORMANT;
- } else if (childState != Constants.FSM_DONE &&
- childState != Constants.GRP_STATE_DONE) {
- return Constants.GRP_SOME_CHILD_RUNNING;
- }
- } // end while there elements in child List
-
- List activeChildren = groupModel.getActiveChildren();
- if (activeChildren.size() > 0) {
- activeChildren.remove(0);
- }
- return Constants.GRP_ALL_CHILDREN_DONE;
- }
-
+ /* Constructor */
+ public SimpleDirectedDialog() {
+ super();
+ }
+
+ /**
+ * Collect the required information from the user
+ *
+ *
+ */
+ public void collect(JspContext ctx, JspFragment bodyFragment)
+ throws JspException, IOException {
+
+ GroupModel groupModel = (GroupModel) stateMap.get(groupTag.getId());
+ Map modelMap = groupModel.getLocalMap();
+
+ if (modelMap.get(Constants.STR_INIT_ONLY_FLAG) == Boolean.TRUE) {
+ // DD starts off with all children in dormant state
+ setStateChildren(modelMap, Constants.FSM_DORMANT);
+ groupState = Constants.GRP_ALL_CHILDREN_DORMANT;
+ groupModel.setState(Constants.GRP_STATE_RUNNING);
+ modelMap.put(Constants.STR_INIT_ONLY_FLAG, Boolean.FALSE);
+ } else {
+ groupState = getGroupState(groupModel);
+ }
+
+ // Real work at the component level is done here
+ if (groupModel.getState() == Constants.GRP_STATE_RUNNING) {
+ do {
+ dialogManagerDD(groupModel);
+ if (bodyFragment != null) {
+ bodyFragment.invoke(null);
+ }
+ } while ((groupState = getGroupState(groupModel)) ==
+ Constants.GRP_SOME_CHILD_DORMANT);
+ }
+ }
+
+
+ /**
+ * This method does the directive dialog management and sets the state
+ * to begin if they are in dormant state
+ *
+ * @param children Map that holds the id's
+ */
+ private void dialogManagerDD(GroupModel groupModel) {
+
+ Map children = groupModel.getLocalMap();
+ if (children == null) {
+ return;
+ }
+
+ Iterator iter = children.keySet().iterator();
+ String currentItem = null;
+ int currentState;
+ BaseModel model = null;
+
+ while (iter.hasNext()) {
+ currentItem = (String) iter.next();
+ if (currentItem.equals(Constants.STR_INIT_ONLY_FLAG)) {
+ continue;
+ }
+
+ model = (BaseModel) children.get(currentItem);
+ currentState = model.getState();
+ List activeChildren = groupModel.getActiveChildren();
+
+ if (currentState != Constants.FSM_DONE &&
+ currentState != Constants.GRP_STATE_DONE){
+ // If the state is FSM_DORMANT, set it to FSM_INPUT
+ if (currentState == Constants.FSM_DORMANT) {
+ if (activeChildren.size() > 0) {
+ activeChildren.remove(0);
+ }
+ activeChildren.add(model.getId());
+ if (model instanceof GroupModel) {
+ model.setState(Constants.GRP_STATE_RUNNING);
+ } else {
+ model.setState(Constants.FSM_INPUT);
+ }
+ }
+ // Else, let child execute till completion
+ return;
+ }
+ // If state is done, move on to next child
+ } // end while iterate over Map children
+
+ } // end method dialogManagerDD()
+
+ /**
+ * Returns the group state based on state of its children
+ *
+ * One of these states will be returned
+ * GRP_SOME_CHILD_RUNNING -> either of the children are in the execution
+ * phase, if the children are not done they are in running state
+ *
+ * GRP_SOME_CHILD_DORMANT -> either of the children are in input state
+ * could be say "done->input->input"
+ *
+ * GRP_ALL_CHILDREN_DONE -> if the child list is empty or if all the
+ * children are done say "done->done->done"
+ *
+ * @param children Map that holds the id's
+ * @return the child state
+ */
+ private int getGroupState(GroupModel groupModel) {
+ Map children = groupModel.getLocalMap();
+ if (children == null) {
+ return Constants.GRP_ALL_CHILDREN_DONE;
+ }
+
+ Iterator iter = children.keySet().iterator();
+ String current;
+ int childState;
+
+ //Loop while there are elements in the list
+ while (iter.hasNext()) {
+ current = (String) iter.next();
+ if (current.equals(Constants.STR_INIT_ONLY_FLAG)) {
+ continue;
+ }
+
+ childState = ((BaseModel) children.get(current)).getState();
+
+ if (childState == Constants.FSM_DORMANT) {
+ return Constants.GRP_SOME_CHILD_DORMANT;
+ } else if (childState != Constants.FSM_DONE &&
+ childState != Constants.GRP_STATE_DONE) {
+ return Constants.GRP_SOME_CHILD_RUNNING;
+ }
+ } // end while there elements in child List
+
+ List activeChildren = groupModel.getActiveChildren();
+ if (activeChildren.size() > 0) {
+ activeChildren.remove(0);
+ }
+ return Constants.GRP_ALL_CHILDREN_DONE;
+ }
+
}
Modified: jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/resources/RDCBundle.properties
URL: http://svn.apache.org/viewcvs/jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/resources/RDCBundle.properties?rev=231329&r1=231328&r2=231329&view=diff
==============================================================================
--- jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/resources/RDCBundle.properties (original)
+++ jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/resources/RDCBundle.properties Wed Aug 10 14:10:59 2005
@@ -23,6 +23,7 @@
</one-of>\n\t</rule>\n\t</grammar>
rdc.alpha.voicegrammar.uri = .grammar/alpha.grxml
rdc.alphanum.voicegrammar.uri = .grammar/alphanum.grxml
+rdc.color.voicegrammar.uri = .grammar/color.grxml
rdc.country.voicegrammar.uri = .grammar/countries.grxml
rdc.creditcard.expiry.voicegrammar.uri = .grammar/cardexpiry.grxml
rdc.creditcard.fullbalance.voicegrammar.uri = .grammar/cardamountextras.grxml#full
@@ -52,14 +53,18 @@
#
rdc.alpha.defaultconfig.uri = META-INF/tags/rdc/config/alpha.xml
rdc.alphanum.defaultconfig.uri = META-INF/tags/rdc/config/alphanum.xml
+rdc.color.defaultconfig.uri = META-INF/tags/rdc/config/color.xml
rdc.country.defaultconfig.uri = META-INF/tags/rdc/config/country.xml
rdc.creditcard.amount.defaultconfig.uri = META-INF/tags/rdc/config/cardamount.xml
rdc.creditcard.expiry.defaultconfig.uri = META-INF/tags/rdc/config/cardexpiry.xml
rdc.creditcard.number.defaultconfig.uri = META-INF/tags/rdc/config/cardnumber.xml
rdc.creditcard.securitycode.defaultconfig.uri = META-INF/tags/rdc/config/cardsecuritycode.xml
rdc.creditcard.type.defaultconfig.uri = META-INF/tags/rdc/config/creditcardtype.xml
+rdc.creditcard.info.securitycode.defaultconfig.uri = META-INF/tags/rdc/config/cardsecuritycode.xml
rdc.currency.defaultconfig.uri = META-INF/tags/rdc/config/currency.xml
rdc.date.defaultconfig.uri = META-INF/tags/rdc/config/date.xml
+rdc.daterange.startdate.defaultconfig.uri = META-INF/tags/rdc/config/dateRangeStartDate.xml
+rdc.daterange.enddate.defaultconfig.uri = META-INF/tags/rdc/config/dateRangeEndDate.xml
rdc.digits.defaultconfig.uri = META-INF/tags/rdc/config/digits.xml
rdc.duration.defaultconfig.uri = META-INF/tags/rdc/config/duration.xml
rdc.isbn.defaultconfig.uri = META-INF/tags/rdc/config/isbn.xml
Modified: jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/resources/RDCBundle_en_US.properties
URL: http://svn.apache.org/viewcvs/jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/resources/RDCBundle_en_US.properties?rev=231329&r1=231328&r2=231329&view=diff
==============================================================================
--- jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/resources/RDCBundle_en_US.properties (original)
+++ jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/resources/RDCBundle_en_US.properties Wed Aug 10 14:10:59 2005
@@ -23,6 +23,7 @@
</one-of>\n\t</rule>\n\t</grammar>
rdc.alpha.voicegrammar.uri = .grammar/alpha.grxml
rdc.alphanum.voicegrammar.uri = .grammar/alphanum.grxml
+rdc.color.voicegrammar.uri = .grammar/color.grxml
rdc.country.voicegrammar.uri = .grammar/countries.grxml
rdc.creditcard.expiry.voicegrammar.uri = .grammar/cardexpiry.grxml
rdc.creditcard.fullbalance.voicegrammar.uri = .grammar/cardamountextras.grxml#full
@@ -52,14 +53,18 @@
#
rdc.alpha.defaultconfig.uri = META-INF/tags/rdc/config/alpha.xml
rdc.alphanum.defaultconfig.uri = META-INF/tags/rdc/config/alphanum.xml
+rdc.color.defaultconfig.uri = META-INF/tags/rdc/config/color.xml
rdc.country.defaultconfig.uri = META-INF/tags/rdc/config/country.xml
rdc.creditcard.amount.defaultconfig.uri = META-INF/tags/rdc/config/cardamount.xml
rdc.creditcard.expiry.defaultconfig.uri = META-INF/tags/rdc/config/cardexpiry.xml
rdc.creditcard.number.defaultconfig.uri = META-INF/tags/rdc/config/cardnumber.xml
rdc.creditcard.securitycode.defaultconfig.uri = META-INF/tags/rdc/config/cardsecuritycode.xml
rdc.creditcard.type.defaultconfig.uri = META-INF/tags/rdc/config/creditcardtype.xml
+rdc.creditcard.info.securitycode.defaultconfig.uri = META-INF/tags/rdc/config/cardsecuritycode.xml
rdc.currency.defaultconfig.uri = META-INF/tags/rdc/config/currency.xml
rdc.date.defaultconfig.uri = META-INF/tags/rdc/config/date.xml
+rdc.daterange.startdate.defaultconfig.uri = META-INF/tags/rdc/config/dateRangeStartDate.xml
+rdc.daterange.enddate.defaultconfig.uri = META-INF/tags/rdc/config/dateRangeEndDate.xml
rdc.digits.defaultconfig.uri = META-INF/tags/rdc/config/digits.xml
rdc.duration.defaultconfig.uri = META-INF/tags/rdc/config/duration.xml
rdc.isbn.defaultconfig.uri = META-INF/tags/rdc/config/isbn.xml
---------------------------------------------------------------------
To unsubscribe, e-mail: taglibs-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: taglibs-dev-help@jakarta.apache.org