1
2
3
4
5
6
7
8
9
10
11
12
13
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
36
37
38
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
51
52
53
54
55 public AbstractMessageBuilder(final String language, final MessageTreeBuilder treeNodeMessageBuilder) {
56 this.language = language;
57 this.treeNodeMessageBuilder = treeNodeMessageBuilder;
58 }
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 public BooleanFunctionResult build(
76 final String booleanExpression,
77 final Map<String, ? extends BooleanMessage> messageMap) {
78 this.booleanExpression = booleanExpression;
79 this.messageMap = messageMap;
80
81 return build();
82 }
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 public BooleanFunctionResult build(
105 final String booleanExpression,
106 final Map<String, ? extends BooleanMessage> messageMap,
107 final Map<String, Object> messageContextMap) {
108 this.booleanExpression = booleanExpression;
109 this.messageMap = messageMap;
110 this.messageContextMap = messageContextMap;
111
112 return build();
113 }
114
115 public BooleanFunctionResult build() {
116 BinaryMessageTree astTree = null;
117
118 try {
119
120 Map<String, BooleanMessage> nodeMessageMap = buildMessageMap();
121
122
123 astTree = new BinaryMessageTree(this.language, nodeMessageMap);
124 BooleanNode root = astTree.buildTree(this.booleanExpression);
125 astTree.traverseTreePostOrder(root, null);
126
127 List<BooleanNode> treeNodes = astTree.getAllNodes();
128
129
130 this.treeNodeMessageBuilder.buildMessage(treeNodes);
131 } catch(VelocityException e) {
132 throw new MessageBuilderException("Building Velocity message failed: " + e.getMessage(), e);
133 } catch (BooleanFunctionException e) {
134 throw new MessageBuilderException("Building message failed: " + e.getMessage(), e);
135 }
136
137
138 String message = astTree.getRoot().getNodeMessage();
139 Boolean result = astTree.getRoot().getValue();
140
141
142 if (message.startsWith("(") && message.endsWith(")") &&
143 message.replaceAll("[^(]","").length() == 1 &&
144 message.replaceAll("[^)]","").length() == 1) {
145 message = message.substring(1, message.length()-1);
146 }
147
148 return new BooleanFunctionResult(this.booleanExpression, result, message);
149 }
150
151
152
153
154
155
156 private Map<String, BooleanMessage> buildMessageMap() {
157 Map<String, BooleanMessage> nodeMessageMap = new HashMap<String, BooleanMessage>();
158
159 if (this.booleanExpression == null || this.booleanExpression.isEmpty()) {
160 throw new MessageBuilderException("Boolean expression is null");
161 }
162
163 BooleanFunction func = new BooleanFunction(this.booleanExpression);
164 List<String> funcVars = func.getVariables();
165
166 if(funcVars == null || funcVars.isEmpty()) {
167 throw new MessageBuilderException("Boolean function variables are null or empty. Boolean expression: " + this.booleanExpression);
168 }
169
170 for (String id : funcVars) {
171 if(id == null) {
172 throw new MessageBuilderException("Boolean variable id is null or empty. Boolean variable ids: " + funcVars);
173 }
174
175 BooleanMessage message = this.messageMap.get(id);
176
177 if (message == null) {
178 throw new MessageBuilderException("Boolean message is null for id='" + id + "'");
179 }
180
181 BooleanMessage booleanMessage = buildMessage(message);
182 nodeMessageMap.put(id, booleanMessage);
183 }
184
185 return nodeMessageMap;
186 }
187
188
189
190
191
192
193
194 private BooleanMessage buildMessage(BooleanMessage message) {
195 String msg = message.getMessage();
196
197 if(msg != null) {
198 msg = this.templateEngine.evaluate(this.messageContextMap, msg);
199 }
200
201 return new BooleanMessageImpl(message.getMessageId(), message.isSuccesful(), msg);
202 }
203 }