001: package com.xoetrope.survey;
002:
003: import java.util.Vector;
004: import java.util.Enumeration;
005: import net.xoetrope.xml.XmlElement;
006: import net.xoetrope.xml.nanoxml.NanoXmlElement;
007: import net.xoetrope.xui.XProject;
008: import net.xoetrope.xui.XProjectManager;
009:
010: /**
011: * DefaultRuleEngine is responsible for managing rules contained in a survey.
012: *
013: * <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
014: * the GNU Public License (GPL), please see license.txt for more details. If
015: * you make commercial use of this software you must purchase a commercial
016: * license from Xoetrope.</p>
017: * <p> $Revision: 1.5 $</p>
018: */
019: public class DefaultRuleEngine implements RuleEngine {
020: protected XProject currentProject;
021: protected SurveyManager surveyManager;
022:
023: public DefaultRuleEngine() {
024: currentProject = XProjectManager.getCurrentProject();
025: surveyManager = (SurveyManager) currentProject
026: .getObject("SurveyManager");
027: }
028:
029: /**
030: * Handles user's answer according to the rules. This method is called after user's
031: * answer for single question.
032: * @param group id of the current question group
033: * @param response
034: * @param rules xml node describing rules of the current survey.
035: */
036: public void handleAnswer(int group, Condition response,
037: XmlElement rules) {
038: }
039:
040: /**
041: * Handles set of answers given by the user. This method is called after user's answer for all
042: * questions from the current question group.
043: * @param group current question group
044: * @param conditions answers given by the user
045: * @param xmlRules xml node describing rules of the current survey.
046: */
047: public void handleGroup(QuestionGroup group, Vector conditions,
048: XmlElement xmlRules) {
049: Survey currentSurvey = surveyManager.getCurrentSurvey();
050: int rlen = conditions.size();
051: Vector rules = createRules(group);
052:
053: int ret = checkRules(rules, conditions);
054: if (ret == -1)
055: ret = group.getNextGroupId();
056: currentSurvey.shiftToGroup(ret);
057: }
058:
059: /**
060: * Creates the xml element describing the specified rules
061: * @param rule Vector containing rules
062: * @return xml element describing specified rules
063: */
064: public XmlElement makeRules(Vector rules) {
065: XmlElement rulesXml = new NanoXmlElement("Rules");
066: Enumeration enumRules = rules.elements();
067: while (enumRules.hasMoreElements()) {
068: DefaultRule rule = (DefaultRule) enumRules.nextElement();
069: String ruleId = String.valueOf(rule.getId());
070: String targetId = null;
071: QuestionGroup targetGroup = rule.getTarget();
072: if (targetGroup != null)
073: targetId = String.valueOf(targetGroup.getId());
074: String ruleName = rule.getName();
075:
076: XmlElement ruleXml = new NanoXmlElement("Rule");
077: ruleXml.setAttribute("id", ruleId);
078: if (targetId != null)
079: ruleXml.setAttribute("target", targetId);
080: ruleXml.setAttribute("name", ruleName);
081:
082: Enumeration enumConditions = rule.getConditions()
083: .elements();
084: while (enumConditions.hasMoreElements()) {
085: Condition condition = (Condition) enumConditions
086: .nextElement();
087: String questionId = String.valueOf(condition
088: .getQuestion().getId());
089: int numAnswers = condition.getAnswers().size();
090: for (int i = 0; i < numAnswers; i++) {
091: String optionId = String
092: .valueOf(((Option) condition.getOptions()
093: .get(i)).getId());
094: String answer = (String) condition.getAnswers()
095: .get(i);
096: XmlElement conditionXml = new NanoXmlElement(
097: "Response");
098: conditionXml.setAttribute("question", questionId);
099: conditionXml.setAttribute("option", optionId);
100: conditionXml.setAttribute("answer", answer);
101: }
102: }
103:
104: rulesXml.addChild(ruleXml);
105: }
106:
107: return rulesXml;
108: }
109:
110: /**
111: * Creates the rules from the xml element stored
112: * in the specified question group.
113: * @param group the question group whose rules
114: * are to be created
115: * @return Vector containing rules.
116: */
117: public Vector createRules(QuestionGroup group) {
118: Survey currentSurvey = surveyManager.getCurrentSurvey();
119: XmlElement rulesRoot = group.getXmlRules();
120: Vector rules = new Vector();
121: if (rulesRoot == null)
122: return rules;
123:
124: Vector xmlRules = rulesRoot.getChildren();
125: if (xmlRules == null)
126: return null;
127:
128: for (int i = 0; i < xmlRules.size(); i++) {
129: XmlElement xmlRule = (XmlElement) xmlRules.get(i);
130: if (!xmlRule.getName().equals("Rule"))
131: continue;
132:
133: int ruleId = new Integer(xmlRule.getAttribute("id"))
134: .intValue();
135:
136: QuestionGroup target = null;
137: String targetIds = xmlRule.getAttribute("target");
138: if (targetIds != null) {
139: int targetId = new Integer(targetIds).intValue();
140: target = currentSurvey.getGroupById(targetId);
141: }
142:
143: String ruleName = xmlRule.getAttribute("name");
144:
145: DefaultRule rule = new DefaultRule(ruleId, group, target,
146: ruleName);
147:
148: Vector xmlResponses = xmlRule.getChildren();
149: int sz = xmlResponses.size();
150: for (int j = 0; j < sz; j++) {
151: XmlElement xmlResponse = (XmlElement) xmlResponses
152: .get(j);
153: if (!xmlResponse.getName().equals("Response"))
154: continue;
155:
156: int questionId = new Integer(xmlResponse
157: .getAttribute("question")).intValue();
158: int optionId = new Integer(xmlResponse
159: .getAttribute("option")).intValue();
160: String answer = xmlResponse.getAttribute("answer");
161: Question question = currentSurvey
162: .getQuestionById(questionId);
163: Option option = question.getOptionById(optionId);
164: rule.addCondition(question, option, answer);
165: }
166: rules.add(rule);
167: }
168: return rules;
169: }
170:
171: /**
172: * Checks whether the specified responses match the specified rules,
173: * if so the target question group is returned
174: * @param rules the rules to be queried
175: * @param respones the responses given by the user
176: * @return the id of the target question group or -1
177: * if the responses and rules do not match.
178: */
179: protected int checkRules(Vector rules, Vector responses) {
180: Enumeration enumeration = rules.elements();
181: int ret = -1;
182: while (enumeration.hasMoreElements() && ret == -1) {
183: DefaultRule rule = (DefaultRule) enumeration.nextElement();
184: ret = rule.checkResponses(responses);
185: }
186:
187: return ret;
188: }
189:
190: }
|