Coverage Report - org.kuali.student.common.messagebuilder.impl.SimpleBooleanMessageBuilder
 
Classes in this File Line Coverage Branch Coverage Complexity
SimpleBooleanMessageBuilder
95%
71/74
68%
44/64
3.429
 
 1  
 package org.kuali.student.common.messagebuilder.impl;
 2  
 
 3  
 import java.util.ArrayList;
 4  
 import java.util.List;
 5  
 
 6  
 import org.kuali.student.common.messagebuilder.MessageTreeBuilder;
 7  
 import org.kuali.student.common.messagebuilder.booleanmessage.ast.BooleanNode;
 8  
 import org.kuali.student.common.messagebuilder.impl.exceptions.MessageBuilderException;
 9  
 
 10  
 /**
 11  
  * This class creates success messages for boolean binary tree nodes.
 12  
  *
 13  
  * Default display is a single line message (e.g. A OR (B AND (C OR D))).  
 14  
  * To display as multiple lines where each operator and message is on its own line.
 15  
  * set the following:
 16  
  * <pre>
 17  
  * INDENT_CHAR = ' '
 18  
  * INDENT_NUMBER_OF_SPACES = 4
 19  
  * BOOLEAN_OPERATOR_PREFIX = "\n"
 20  
  * BOOLEAN_OPERATOR_SUFFIX = "\n"
 21  
  * Example:
 22  
  * </pre>
 23  
  * <pre>
 24  
  *    MATH101
 25  
  * OR
 26  
  *        (MATH201
 27  
  *    AND
 28  
  *            (MATH301
 29  
  *        OR
 30  
  *            MATH401))
 31  
  * </pre>
 32  
  */
 33  
 public class SimpleBooleanMessageBuilder implements MessageTreeBuilder {
 34  
         // Default indentation character
 35  
         private final static char INDENT_CHAR = 0;
 36  
         // Default number of spaces to indent
 37  
         private final static int INDENT_NUMBER_OF_SPACES = 0;
 38  
         // Default indentation string
 39  1
         private final static String INDENT_STRING = getString(INDENT_NUMBER_OF_SPACES, INDENT_CHAR);
 40  
         // Default boolean operator prefix string
 41  
         private final static String BOOLEAN_OPERATOR_PREFIX = " ";
 42  
         // Default boolean operator suffix string
 43  
         private final static String BOOLEAN_OPERATOR_SUFFIX = " ";
 44  
 
 45  
         // Indentation character
 46  14
         private int indentCharacter = INDENT_CHAR;
 47  
         // Number of spaces to indent
 48  14
         private int indentNumberOfSpaces = INDENT_NUMBER_OF_SPACES;
 49  
         // Indentation string
 50  14
         private String indentString = INDENT_STRING;
 51  
         // Boolean operator prefix string
 52  14
         private String booleanOperatorPrefix = BOOLEAN_OPERATOR_PREFIX;
 53  
         // Boolean operator suffix string
 54  14
         private String booleanOperatorSuffix = BOOLEAN_OPERATOR_SUFFIX;
 55  
         
 56  
         /** Boolean operators to use in creating the success message */
 57  
         private BooleanOperators booleanOperators;
 58  
 
 59  
         /**
 60  
          * Creates a success message builder with boolean operators to use in 
 61  
          * building the success message.
 62  
          * 
 63  
          * @param andOperator AND logical operator
 64  
          * @param orOperator OR logical operator
 65  
          */
 66  0
         public SimpleBooleanMessageBuilder(String andOperator, String orOperator) {
 67  0
                 this.booleanOperators = new BooleanOperators(andOperator, orOperator);
 68  0
         }
 69  
 
 70  
         /**
 71  
          * Creates a success message builder with boolean operators to use in 
 72  
          * building the success message.
 73  
          * 
 74  
          * @param bo Boolean operators to build success message
 75  
          */
 76  14
         public SimpleBooleanMessageBuilder(BooleanOperators bo) {
 77  14
                 this.booleanOperators = bo;
 78  14
         }
 79  
 
 80  
         public void setIndentCharacter(int indentChar) {
 81  7
                 this.indentCharacter = indentChar;
 82  7
         }
 83  
 
 84  
         public void setIndentNumberOfSpaces(int indentNumberOfSpaces) {
 85  7
                 this.indentNumberOfSpaces = indentNumberOfSpaces;
 86  7
         }
 87  
 
 88  
         public void setIndentString(String indentString) {
 89  7
                 this.indentString = indentString;
 90  7
         }
 91  
 
 92  
         public void setBooleanOperatorPrefix(String booleanOperatorPrefix) {
 93  7
                 this.booleanOperatorPrefix = booleanOperatorPrefix;
 94  7
         }
 95  
 
 96  
         public void setBooleanOperatorSuffix(String booleanOperatorSuffix) {
 97  7
                 this.booleanOperatorSuffix = booleanOperatorSuffix;
 98  7
         }
 99  
 
 100  
         /**
 101  
          * Builds and sets the success message for each of the boolean nodes 
 102  
          * (binary tree) in the <code>nodeList</code>.
 103  
          * 
 104  
          * @param nodeList List of boolean nodes 
 105  
          * @return Complete success message 
 106  
          */
 107  
         public String buildMessage(List<BooleanNode> nodeList) throws MessageBuilderException {
 108  
                 // List must only contain one root node
 109  4
                 List<BooleanNode> rootNodeList = new ArrayList<BooleanNode>();
 110  4
                 for(BooleanNode node : nodeList) {
 111  23
                         if(node.getParent() == null) {
 112  5
                                 rootNodeList.add(node);
 113  
                         }
 114  23
                         buildMessage(node);
 115  
                 }
 116  4
                 if(rootNodeList.size() > 1) {
 117  1
                         throw new MessageBuilderException("Node list contains more than one root node: " + rootNodeList);
 118  
                 }
 119  3
                 return rootNodeList.get(0).getNodeMessage();
 120  
         }
 121  
 
 122  
         /**
 123  
          * Builds and sets the success message for a single 
 124  
          * boolean <code>node</code> (b-tree node).
 125  
          * 
 126  
          * @param node Boolean node
 127  
          */
 128  
         public String buildMessage(final BooleanNode node) {
 129  
                 // AND node
 130  26
                 if(node.getLabel().equals("*")) {
 131  7
                         buildAndNodeSuccessMessage(node);
 132  
                 } 
 133  
                 // OR node
 134  19
                 else if(node.getLabel().equals("+")) {
 135  7
                         buildOrNodeSuccessMessage(node);
 136  
                 }
 137  26
                 return node.getNodeMessage();
 138  
         }
 139  
 
 140  
         /**
 141  
          * Builds a success message for an AND node (b-tree node) where 
 142  
          * left node and right node are true.
 143  
          * 
 144  
          * @param node Boolean node
 145  
          */
 146  
         private void buildAndNodeSuccessMessage(BooleanNode node) {
 147  7
                 if(node.getLabel().equals("*") && 
 148  
                                 node.getLeftNode() != null && 
 149  
                                 node.getRightNode() != null &&
 150  
                                 node.getLeftNode().getNodeMessage() != null && 
 151  
                                 node.getRightNode().getNodeMessage() != null) {
 152  6
                         String preIndent = "";
 153  6
                         if(node.getLeftNode().getChildCount() == 0) {
 154  6
                                 preIndent = getIndent(node, 0);
 155  
                         }
 156  6
                         String postIndent = "";
 157  6
                         if(node.getRightNode().getChildCount() == 0) {
 158  3
                                 postIndent = getIndent(node, 0);
 159  
                         }
 160  
 
 161  6
                         String logMessage = this.indentString + node.getLeftNode().getNodeMessage() + 
 162  
                                 this.booleanOperatorPrefix + 
 163  
                                 preIndent + this.booleanOperators.getAndOperator() + 
 164  
                                 this.booleanOperatorSuffix + 
 165  
                                 postIndent + this.indentString + node.getRightNode().getNodeMessage();
 166  
 
 167  6
                         if(node.getParent() != null && 
 168  
                                         ((node.getLabel().equals("+") && 
 169  
                                                         node.getParent().getLabel().equals("*")) || 
 170  
                                                         (node.getLabel().equals("*") && 
 171  
                                                                         node.getParent().getLabel().equals("+")))) {
 172  3
                                 logMessage = node.getLeftNode().getNodeMessage() + 
 173  
                                         this.booleanOperatorPrefix + 
 174  
                                         preIndent + this.booleanOperators.getAndOperator() + 
 175  
                                         this.booleanOperatorSuffix + 
 176  
                                         postIndent + this.indentString + node.getRightNode().getNodeMessage();
 177  3
                                     logMessage = preIndent + "(" + logMessage + ")";
 178  
                         }
 179  6
                         node.setNodeMessage(logMessage);
 180  
                 }
 181  7
         }
 182  
 
 183  
         /**
 184  
          * Builds a success message for an OR node (b-tree node) where 
 185  
          * left node and right node are true.
 186  
          * 
 187  
          * @param node
 188  
          */
 189  
         private void buildOrNodeSuccessMessage(BooleanNode node) {
 190  
                 // OR2
 191  7
                 if(node.getLabel().equals("+") &&
 192  
                                 node.getLeftNode() != null && 
 193  
                                 node.getRightNode() != null &&
 194  
                                 node.getLeftNode().getNodeMessage() != null && 
 195  
                                 node.getRightNode().getNodeMessage() != null) {
 196  6
                         String preIndent = "";
 197  6
                         if(node.getLeftNode().getChildCount() == 0) {
 198  5
                                 preIndent = getIndent(node, 0);
 199  
                         }
 200  6
                         String postIndent = "";
 201  6
                         if(node.getRightNode().getChildCount() == 0) {
 202  4
                                 postIndent = getIndent(node, 0);
 203  
                         }
 204  
 
 205  6
                         String logMessage = this.indentString + node.getLeftNode().getNodeMessage() + 
 206  
                         this.booleanOperatorPrefix + 
 207  
                                 preIndent + this.booleanOperators.getOrOperator() + 
 208  
                                 this.booleanOperatorSuffix + 
 209  
                                 postIndent + this.indentString + node.getRightNode().getNodeMessage();
 210  
 
 211  6
                         if(node.getParent() != null && 
 212  
                                         ((node.getLabel().equals("+") && 
 213  
                                                         node.getParent().getLabel().equals("*")) || 
 214  
                                                         (node.getLabel().equals("*") && 
 215  
                                                                         node.getParent().getLabel().equals("+")))) {
 216  3
                                 logMessage = node.getLeftNode().getNodeMessage() + 
 217  
                                         this.booleanOperatorPrefix + 
 218  
                                         preIndent + this.booleanOperators.getOrOperator() + 
 219  
                                         this.booleanOperatorSuffix + 
 220  
                                         postIndent + this.indentString + node.getRightNode().getNodeMessage();
 221  3
                                     logMessage = preIndent + "(" + logMessage + ")";
 222  
                         }
 223  6
                         node.setNodeMessage(logMessage);
 224  
                 } 
 225  7
         }
 226  
         
 227  
         private int parentCount;
 228  
         
 229  
         private void countParents(BooleanNode node) {
 230  32
                 if(node.getParent() != null) {
 231  14
                         this.parentCount++;
 232  14
                         countParents(node.getParent());
 233  
                 }
 234  32
         }
 235  
         
 236  
         private String getIndent(BooleanNode node, int multiplier) {
 237  18
                 this.parentCount = 0;
 238  18
                 countParents(node);
 239  18
                 if(this.parentCount > 0) {
 240  10
                         return getString(this.parentCount * this.indentNumberOfSpaces + multiplier, (char) this.indentCharacter);
 241  
                 }
 242  8
                 return "";
 243  
         }
 244  
         
 245  
         private static String getString(int charCount, char indentChr) {
 246  11
                 char[] chr = new char[charCount];
 247  59
                 for(int i=0; i<chr.length; i++) {
 248  48
                         chr[i] = indentChr;
 249  
                 }
 250  11
                 return String.valueOf(chr);
 251  
         }
 252  
 }