|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
AbstractMessageBuilder | Line # 40 | 44 | 0% | 19 | 9 | 85.5% |
0.8548387
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
(38) | |||
Result | |||
0.6935484
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage6 org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage6 | 1 PASS | |
0.67741936
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage11 org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage11 | 1 PASS | |
0.67741936
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage5_True org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage5_True | 1 PASS | |
0.67741936
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessageTemplate1_NullContextMap_True org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessageTemplate1_NullContextMap_True | 1 PASS | |
0.67741936
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessageTemplate3_True org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessageTemplate3_True | 1 PASS | |
0.67741936
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessageTemplate4_False org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessageTemplate4_False | 1 PASS | |
0.67741936
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessageTemplate2_NullContextMap_False org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessageTemplate2_NullContextMap_False | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessageTemplate2_NullContextMap_False org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessageTemplate2_NullContextMap_False | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessageTemplate2_NullContextMap_False org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessageTemplate2_NullContextMap_False | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessageTemplate2_NullContextMap_False org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessageTemplate2_NullContextMap_False | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessageTemplate2_NullContextMap_False org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessageTemplate2_NullContextMap_False | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage9 org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage9 | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage9 org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage9 | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage12 org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage12 | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage13 org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage13 | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage13 org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage13 | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage3_False org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage3_False | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage8 org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage8 | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage8 org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage8 | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage4_False org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage4_False | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage4_False org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage4_False | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage2_True org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage2_True | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage2_True org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage2_True | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage1_True org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage1_True | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage1_True org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage1_True | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage1_True org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage1_True | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage7 org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage7 | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage7 org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage7 | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage7 org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage7 | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage7 org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage7 | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage7 org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage7 | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage7 org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage7 | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage7 org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage7 | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage10 org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage10 | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage10 org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage10 | 1 PASS | |
0.66129035
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage10 org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage10 | 1 PASS | |
0.516129
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessageTemplate5_False_Exception org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessageTemplate5_False_Exception | 1 PASS | |
0.22580644
|
org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage1_InvalidBooleanExpression org.kuali.student.common.messagebuilder.impl.MessageBuilderImplTest.testBuildMessage1_InvalidBooleanExpression | 1 PASS | |
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.impl; | |
17 | ||
18 | import java.util.HashMap; | |
19 | import java.util.List; | |
20 | import java.util.Map; | |
21 | ||
22 | import org.apache.velocity.exception.VelocityException; | |
23 | import org.kuali.student.common.messagebuilder.MessageTreeBuilder; | |
24 | import org.kuali.student.common.messagebuilder.booleanmessage.BooleanMessage; | |
25 | import org.kuali.student.common.messagebuilder.booleanmessage.ast.BinaryMessageTree; | |
26 | import org.kuali.student.common.messagebuilder.booleanmessage.ast.BooleanFunction; | |
27 | import org.kuali.student.common.messagebuilder.booleanmessage.ast.BooleanFunctionResult; | |
28 | import org.kuali.student.common.messagebuilder.booleanmessage.ast.BooleanMessageImpl; | |
29 | import org.kuali.student.common.messagebuilder.booleanmessage.ast.BooleanNode; | |
30 | import org.kuali.student.common.messagebuilder.booleanmessage.ast.exceptions.BooleanFunctionException; | |
31 | import org.kuali.student.common.messagebuilder.impl.exceptions.MessageBuilderException; | |
32 | import org.kuali.student.common.util.VelocityTemplateEngine; | |
33 | ||
34 | /** | |
35 | * This <code>AbstractMessageBuilder</code> class builds a summary message | |
36 | * from plain strings or Velocity template messages. Summary message is built | |
37 | * from analysing the outcome of a boolean expression. | |
38 | * If no language is specified then the default language locale is used. | |
39 | */ | |
40 | public abstract class AbstractMessageBuilder { | |
41 | private final VelocityTemplateEngine templateEngine = new VelocityTemplateEngine(); | |
42 | ||
43 | private String booleanExpression; | |
44 | private Map<String, ? extends BooleanMessage> messageMap; | |
45 | private Map<String, Object> messageContextMap; | |
46 | private String language; | |
47 | private MessageTreeBuilder treeNodeMessageBuilder; | |
48 | ||
49 | /** | |
50 | * Constructor. | |
51 | * | |
52 | * @param language Language | |
53 | * @param treeNodeMessageBuilder AST tree node Message builder | |
54 | */ | |
55 | 30 | public AbstractMessageBuilder(final String language, final MessageTreeBuilder treeNodeMessageBuilder) { |
56 | 30 | this.language = language; |
57 | 30 | this.treeNodeMessageBuilder = treeNodeMessageBuilder; |
58 | } | |
59 | ||
60 | /** | |
61 | * <p>Builds and evaluates a boolean expression and returns the message and result | |
62 | * of the expression. Messages in the <code>messageMap</code> can | |
63 | * also contain VTL (Velocity Template Language) but without any VTL keys</p> | |
64 | * <p><b>Note:</b> Order of boolean operation: ANDs before ORs and operations | |
65 | * inside parentheses before anything else.</p> | |
66 | * Example 1: 'A AND B OR C AND D' internally evaluates to '(A AND B) OR (C AND D)' | |
67 | * <pre><code>booleanExpression</code> = "A*B+C*D"</pre> | |
68 | * Example 2: '(M1 AND M2) OR M3' | |
69 | * <pre><code>booleanExpression</code> = "(M1*M2)+M3"</pre> | |
70 | * | |
71 | * @param booleanExpression Boolean expression | |
72 | * @param messageMap Contains a map of messages (or VTL) | |
73 | * @return Boolean function result | |
74 | */ | |
75 | 39 | public BooleanFunctionResult build( |
76 | final String booleanExpression, | |
77 | final Map<String, ? extends BooleanMessage> messageMap) { | |
78 | 39 | this.booleanExpression = booleanExpression; |
79 | 39 | this.messageMap = messageMap; |
80 | ||
81 | 39 | return build(); |
82 | } | |
83 | ||
84 | /** | |
85 | * <p>Builds and evaluates a boolean expression and returns the message and result | |
86 | * of the expression. Messages in the <code>messageMap</code> can | |
87 | * also contain VTL (Velocity Template Language). | |
88 | * <code>messageContextMap</code> contains Velocity key/value entries | |
89 | * referenced in the <code>messageMap</code>.</p> | |
90 | * <p><b>Note:</b> Order of boolean operation: ANDs before ORs and operations | |
91 | * inside parentheses before anything else.</p> | |
92 | * Example 1: 'A AND B OR C AND D' internally evaluates to '(A AND B) OR (C AND D)' | |
93 | * <pre><code>booleanExpression</code> = "A*B+C*D"</pre> | |
94 | * Example 2: '(M1 AND M2) OR M3' | |
95 | * <pre><code>booleanExpression</code> = "(M1*M2)+M3"</pre> | |
96 | * | |
97 | * | |
98 | * @param booleanExpression Boolean expression | |
99 | * @param messageMap Contains a map of messages (or VTL) | |
100 | * @param messageContextMap Message contact map for Velocity Template Engine | |
101 | * @return Boolean function result | |
102 | * @throws MessageBuilderException Errors building message | |
103 | */ | |
104 | 5 | public BooleanFunctionResult build( |
105 | final String booleanExpression, | |
106 | final Map<String, ? extends BooleanMessage> messageMap, | |
107 | final Map<String, Object> messageContextMap) { | |
108 | 5 | this.booleanExpression = booleanExpression; |
109 | 5 | this.messageMap = messageMap; |
110 | 5 | this.messageContextMap = messageContextMap; |
111 | ||
112 | 5 | return build(); |
113 | } | |
114 | ||
115 | 44 | public BooleanFunctionResult build() { |
116 | 44 | BinaryMessageTree astTree = null; |
117 | ||
118 | 44 | try { |
119 | // set the functionString and Maps from the proposition container | |
120 | 44 | Map<String, BooleanMessage> nodeMessageMap = buildMessageMap(); |
121 | ||
122 | // go parse function in buildTree | |
123 | 42 | astTree = new BinaryMessageTree(this.language, nodeMessageMap); |
124 | 42 | BooleanNode root = astTree.buildTree(this.booleanExpression); |
125 | 42 | astTree.traverseTreePostOrder(root, null); |
126 | ||
127 | 42 | List<BooleanNode> treeNodes = astTree.getAllNodes(); |
128 | // tree node order in the list is important for building | |
129 | // the success and failure message | |
130 | 42 | this.treeNodeMessageBuilder.buildMessage(treeNodes); |
131 | } catch(VelocityException e) { | |
132 | 1 | throw new MessageBuilderException("Building Velocity message failed: " + e.getMessage(), e); |
133 | } catch (BooleanFunctionException e) { | |
134 | 1 | throw new MessageBuilderException("Building message failed: " + e.getMessage(), e); |
135 | } | |
136 | ||
137 | // This is the final rule report message summary | |
138 | 42 | String message = astTree.getRoot().getNodeMessage(); |
139 | 42 | Boolean result = astTree.getRoot().getValue(); |
140 | ||
141 | // Removed starting and ending brackets if they are the only brackets in the message | |
142 | 42 | if (message.startsWith("(") && message.endsWith(")") && |
143 | message.replaceAll("[^(]","").length() == 1 && | |
144 | message.replaceAll("[^)]","").length() == 1) { | |
145 | 4 | message = message.substring(1, message.length()-1); |
146 | } | |
147 | ||
148 | 42 | return new BooleanFunctionResult(this.booleanExpression, result, message); |
149 | } | |
150 | ||
151 | /** | |
152 | * Builds message map. Also builds message map using velocity templates. | |
153 | * | |
154 | * @return Boolean message map | |
155 | */ | |
156 | 44 | private Map<String, BooleanMessage> buildMessageMap() { |
157 | 44 | Map<String, BooleanMessage> nodeMessageMap = new HashMap<String, BooleanMessage>(); |
158 | ||
159 | 44 | if (this.booleanExpression == null || this.booleanExpression.isEmpty()) { |
160 | 0 | throw new MessageBuilderException("Boolean expression is null"); |
161 | } | |
162 | ||
163 | 44 | BooleanFunction func = new BooleanFunction(this.booleanExpression); |
164 | 43 | List<String> funcVars = func.getVariables(); |
165 | ||
166 | 43 | if(funcVars == null || funcVars.isEmpty()) { |
167 | 0 | throw new MessageBuilderException("Boolean function variables are null or empty. Boolean expression: " + this.booleanExpression); |
168 | } | |
169 | ||
170 | 43 | for (String id : funcVars) { |
171 | 114 | if(id == null) { |
172 | 0 | throw new MessageBuilderException("Boolean variable id is null or empty. Boolean variable ids: " + funcVars); |
173 | } | |
174 | ||
175 | 114 | BooleanMessage message = this.messageMap.get(id); |
176 | ||
177 | 114 | if (message == null) { |
178 | 0 | throw new MessageBuilderException("Boolean message is null for id='" + id + "'"); |
179 | } | |
180 | ||
181 | 114 | BooleanMessage booleanMessage = buildMessage(message); |
182 | 113 | nodeMessageMap.put(id, booleanMessage); |
183 | } | |
184 | ||
185 | 42 | return nodeMessageMap; |
186 | } | |
187 | ||
188 | /** | |
189 | * Builds a failure/success message using the Velocity template engine. | |
190 | * | |
191 | * @param message Boolean failure/success message | |
192 | * @return | |
193 | */ | |
194 | 114 | private BooleanMessage buildMessage(BooleanMessage message) { |
195 | 114 | String msg = message.getMessage(); |
196 | ||
197 | 114 | if(msg != null) { |
198 | 114 | msg = this.templateEngine.evaluate(this.messageContextMap, msg); |
199 | } | |
200 | ||
201 | 113 | return new BooleanMessageImpl(message.getMessageId(), message.isSuccesful(), msg); |
202 | } | |
203 | } |
|