| 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 | 19 |      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 | 19 |      public AbstractMessageBuilder(final String language, final MessageTreeBuilder treeNodeMessageBuilder) { | 
  | 56 | 19 |          this.language = language;  | 
  | 57 | 19 |          this.treeNodeMessageBuilder = treeNodeMessageBuilder; | 
  | 58 | 19 |      } | 
  | 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 | 16 |              this.booleanExpression = booleanExpression; | 
  | 79 | 16 |              this.messageMap = messageMap; | 
  | 80 |  |   | 
  | 81 | 16 |              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 | 5 |              this.booleanExpression = booleanExpression; | 
  | 109 | 5 |              this.messageMap = messageMap; | 
  | 110 | 5 |              this.messageContextMap = messageContextMap; | 
  | 111 |  |   | 
  | 112 | 5 |              return build(); | 
  | 113 |  |      } | 
  | 114 |  |       | 
  | 115 |  |      public BooleanFunctionResult build() { | 
  | 116 | 21 |              BinaryMessageTree astTree = null; | 
  | 117 |  |   | 
  | 118 |  |          try { | 
  | 119 |  |               | 
  | 120 | 21 |                  Map<String, BooleanMessage> nodeMessageMap = buildMessageMap(); | 
  | 121 |  |   | 
  | 122 |  |               | 
  | 123 | 19 |              astTree = new BinaryMessageTree(this.language, nodeMessageMap); | 
  | 124 | 19 |              BooleanNode root = astTree.buildTree(this.booleanExpression); | 
  | 125 | 19 |              astTree.traverseTreePostOrder(root, null); | 
  | 126 |  |   | 
  | 127 | 19 |              List<BooleanNode> treeNodes = astTree.getAllNodes(); | 
  | 128 |  |               | 
  | 129 |  |               | 
  | 130 | 19 |              this.treeNodeMessageBuilder.buildMessage(treeNodes); | 
  | 131 | 1 |          } catch(VelocityException e) { | 
  | 132 | 1 |              throw new MessageBuilderException("Building Velocity message failed: " + e.getMessage(), e); | 
  | 133 | 1 |              } catch (BooleanFunctionException e) { | 
  | 134 | 1 |              throw new MessageBuilderException("Building message failed: " + e.getMessage(), e); | 
  | 135 | 19 |          } | 
  | 136 |  |   | 
  | 137 |  |           | 
  | 138 | 19 |          String message = astTree.getRoot().getNodeMessage(); | 
  | 139 | 19 |          Boolean result = astTree.getRoot().getValue(); | 
  | 140 |  |           | 
  | 141 |  |                   | 
  | 142 | 19 |          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 | 19 |          return new BooleanFunctionResult(this.booleanExpression, result, message); | 
  | 149 |  |      } | 
  | 150 |  |   | 
  | 151 |  |       | 
  | 152 |  |   | 
  | 153 |  |   | 
  | 154 |  |   | 
  | 155 |  |   | 
  | 156 |  |      private Map<String, BooleanMessage> buildMessageMap() { | 
  | 157 | 21 |              Map<String, BooleanMessage> nodeMessageMap = new HashMap<String, BooleanMessage>(); | 
  | 158 |  |   | 
  | 159 | 21 |          if (this.booleanExpression == null || this.booleanExpression.isEmpty()) { | 
  | 160 | 0 |                  throw new MessageBuilderException("Boolean expression is null"); | 
  | 161 |  |          } | 
  | 162 |  |           | 
  | 163 | 21 |          BooleanFunction func = new BooleanFunction(this.booleanExpression); | 
  | 164 | 20 |          List<String> funcVars = func.getVariables(); | 
  | 165 |  |   | 
  | 166 | 20 |              if(funcVars == null || funcVars.isEmpty()) { | 
  | 167 | 0 |                      throw new MessageBuilderException("Boolean function variables are null or empty. Boolean expression: " + this.booleanExpression); | 
  | 168 |  |              }  | 
  | 169 |  |           | 
  | 170 | 20 |          for (String id : funcVars) { | 
  | 171 | 68 |                  if(id == null) { | 
  | 172 | 0 |                          throw new MessageBuilderException("Boolean variable id is null or empty. Boolean variable ids: " + funcVars); | 
  | 173 |  |                  }  | 
  | 174 |  |   | 
  | 175 | 68 |                  BooleanMessage message = this.messageMap.get(id); | 
  | 176 |  |                   | 
  | 177 | 68 |                  if (message == null) { | 
  | 178 | 0 |                          throw new MessageBuilderException("Boolean message is null for id='" + id + "'"); | 
  | 179 |  |                  } | 
  | 180 |  |                   | 
  | 181 | 68 |                  BooleanMessage booleanMessage = buildMessage(message); | 
  | 182 | 67 |              nodeMessageMap.put(id, booleanMessage); | 
  | 183 | 67 |          } | 
  | 184 |  |           | 
  | 185 | 19 |          return nodeMessageMap; | 
  | 186 |  |      } | 
  | 187 |  |   | 
  | 188 |  |       | 
  | 189 |  |   | 
  | 190 |  |   | 
  | 191 |  |   | 
  | 192 |  |   | 
  | 193 |  |   | 
  | 194 |  |      private BooleanMessage buildMessage(BooleanMessage message) { | 
  | 195 | 68 |                  String msg = message.getMessage(); | 
  | 196 |  |   | 
  | 197 | 68 |                  if(msg != null) { | 
  | 198 | 68 |                      msg = this.templateEngine.evaluate(this.messageContextMap, msg); | 
  | 199 |  |                  } | 
  | 200 |  |   | 
  | 201 | 67 |              return new BooleanMessageImpl(message.getMessageId(), message.isSuccesful(), msg); | 
  | 202 |  |      } | 
  | 203 |  |  } |