Clover Coverage Report - Kuali Student 1.2-M2-SNAPSHOT (Aggregated)
Coverage timestamp: Fri Apr 22 2011 04:03:20 EST
../../../../../../../img/srcFileCovDistChart9.png 32% of files have more coverage
52   211   22   5.78
22   112   0.42   9
9     2.44  
1    
 
  BinaryMessageTree       Line # 38 52 0% 22 8 90.4% 0.90361446
 
  (44)
 
1    /**
2    * Copyright 2010 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10    * software distributed under the License is distributed on an "AS IS"
11    * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12    * or implied. See the License for the specific language governing
13    * permissions and limitations under the License.
14    */
15   
16    package org.kuali.student.common.messagebuilder.booleanmessage.ast;
17   
18    import java.util.ArrayList;
19    import java.util.List;
20    import java.util.Locale;
21    import java.util.Map;
22   
23    import org.antlr.runtime.ANTLRStringStream;
24    import org.antlr.runtime.CommonTokenStream;
25    import org.antlr.runtime.RecognitionException;
26    import org.antlr.runtime.Token;
27    import org.antlr.runtime.tree.CommonTreeAdaptor;
28    import org.antlr.runtime.tree.TreeAdaptor;
29   
30    import org.kuali.student.common.messagebuilder.booleanmessage.BooleanMessage;
31    import org.kuali.student.common.messagebuilder.booleanmessage.ast.exceptions.BooleanFunctionException;
32    import org.kuali.student.common.messagebuilder.booleanmessage.ast.parsers.BooleanFunctionLexer;
33    import org.kuali.student.common.messagebuilder.booleanmessage.ast.parsers.BooleanFunctionParser;
34   
35    import org.slf4j.Logger;
36    import org.slf4j.LoggerFactory;
37   
 
38    public class BinaryMessageTree {
39    /** SLF4J logging framework */
40    final static Logger logger = LoggerFactory.getLogger(BinaryMessageTree.class);
41   
42    private BooleanNode root;
43    private ArrayList<BooleanNode> nodes;
44    private String language;
45   
46    private Map<String, ? extends BooleanMessage> nodeMessageMap;
47   
48    private static final TreeAdaptor adaptor = new CommonTreeAdaptor() {
 
49  1144 toggle public Object create(Token payload) {
50  1144 return new BooleanNode(payload);
51    }
52    };
53   
54    /**
55    * Constructor.
56    */
 
57  47 toggle public BinaryMessageTree() {
58  47 language = Locale.getDefault().getLanguage();
59  47 nodes = new ArrayList<BooleanNode>();
60    }
61   
62    /**
63    * Constructor.
64    * Creates a new binary message tree for the in the specified language
65    * for the boolean message map.
66    *
67    * @param messageLanguage Language for the message
68    * @param messageMap map of boolean messages
69    */
 
70  45 toggle public BinaryMessageTree(String language, Map<String, ? extends BooleanMessage> messageMap) {
71  45 this.language = language;
72  45 nodeMessageMap = messageMap;
73  45 nodes = new ArrayList<BooleanNode>();
74    }
75   
76    /**
77    * <p>Builds the binary message tree from the <code>booleanFunction</code>.</p>
78    * <p>Order of boolean operation: ANDs before ORs and
79    * operations inside parentheses before anything else.</p>
80    * <p>Example: A AND B OR C AND D evaluates to (A AND B) OR (C AND D).</p>
81    *
82    * @param booleanFunction: Boolean expression
83    * @return Root boolean node
84    */
 
85  92 toggle public BooleanNode buildTree(String booleanFunction){
86  92 if (booleanFunction == null || booleanFunction.trim().isEmpty()) {
87  0 return null;
88    }
89   
90  92 BooleanFunctionLexer lex = new BooleanFunctionLexer(new ANTLRStringStream(booleanFunction) );
91  92 CommonTokenStream tokens = new CommonTokenStream(lex);
92   
93  92 BooleanFunctionParser parser = new BooleanFunctionParser(tokens);
94  92 parser.setTreeAdaptor(adaptor);
95   
96    // parse the expression
97  92 BooleanFunctionParser.booleanExpression_return booleanExpression = null;
98  92 try {
99  92 booleanExpression = parser.booleanExpression();
100    } catch (RecognitionException e) {
101  1 String parserErrorMsg = parser.getErrorMessage(e, parser.getTokenNames());
102  1 String errorMsg = "Boolean Function Parser Error. " +
103    "Invalid Boolean Expression: '" + booleanFunction + "'; " + parserErrorMsg;
104  1 throw new BooleanFunctionException(errorMsg, e);
105    }
106    // get the root of the AST from the parsed expression
107  91 return root = (BooleanNode) booleanExpression.getTree();
108    }
109   
110    /**
111    * This method walks the tree depth first, while setting node values with
112    * setNode(). Setting a nodes parent and adding the node to the ArrayList
113    * for later. This method has to be called after buildTree.
114    *
115    * @param bnode Boolean node
116    * @param parent Parent boolean node
117    */
 
118  185 toggle public void traverseTreePostOrder(BooleanNode bnode, BooleanNode parent) {
119  327 for (int i = 0; i < bnode.getChildCount(); i++) {
120  142 traverseTreePostOrder((BooleanNode) bnode.getChild(i), bnode);
121    }
122  185 setNode(bnode);
123  185 if (parent != null) {
124  142 bnode.setParent(parent);
125    }
126   
127  185 if(logger.isDebugEnabled()) {
128  0 logger.debug(bnode.getText());
129    }
130  185 nodes.add(bnode);
131    }
132   
133    /**
134    * This method walks the tree depth first. Setting a nodes parent and
135    * adding the node to the ArrayList for later.
136    * This method has to be called after buildTree.
137    *
138    * @param bnode Boolean node
139    * @param parent Parent boolean node
140    */
 
141  195 toggle public void traverseTreePostOrderDontSetNode(BooleanNode bnode, BooleanNode parent) {
142  195 if (bnode != null) {
143  345 for (int i = 0; i < bnode.getChildCount(); i++ ) {
144  150 traverseTreePostOrderDontSetNode((BooleanNode)bnode.getChild(i), bnode);
145    }
146   
147  195 if (parent != null) {
148  150 bnode.setParent(parent);
149    }
150   
151  195 if(logger.isDebugEnabled()) {
152  0 logger.debug(bnode.getText());
153    }
154  195 nodes.add(bnode);
155    }
156    }
157   
158    /**
159    * Here we set the value(true or false) and the failure message for each node.
160    * Setting the failure message here does not mean the function failed, the node just holds the message.
161    * Failure is determined by the rules engine which will extract the failure message.
162    *
163    * @param bnode Boolean node
164    */
 
165  185 toggle private void setNode(BooleanNode bnode) {
166  185 bnode.setLanguage(language);
167   
168  185 if (bnode.getChildCount() == 0) {
169    // If node is a leaf then set value and message
170  114 BooleanMessage message = nodeMessageMap.get(bnode.getLabel());
171  114 bnode.setValue(message.isSuccesful());
172  114 bnode.setNodeMessage(message.getMessage());
173    }
174    else {
175    // If node is intermediate, compute value and set it
176  71 BooleanNode child0 = (BooleanNode)bnode.getChild(0);
177  71 BooleanNode child1 = (BooleanNode)bnode.getChild(1);
178   
179  71 if ( bnode.getLabel().equalsIgnoreCase("+") ) {
180    // OR node
181  33 Boolean newValue = child0.getValue() || child1.getValue();
182  33 bnode.setValue(newValue);
183  33 bnode.setNodeMessage("null");
184    }
185  38 else if ( bnode.getLabel().equalsIgnoreCase("*") ) {
186    // AND node
187  38 Boolean newValue = child0.getValue() && child1.getValue();
188  38 bnode.setValue(newValue);
189  38 bnode.setNodeMessage("null");
190    }
191    }
192    }
193   
194    /**
195    * Gets all boolean nodes.
196    *
197    * @return All boolean nodes
198    */
 
199  88 toggle public List<BooleanNode> getAllNodes() {
200  88 return nodes;
201    }
202   
203    /**
204    * Gets the root boolean node.
205    *
206    * @return Root boolean node
207    */
 
208  85 toggle public BooleanNode getRoot() {
209  85 return root;
210    }
211    }