001    package org.kuali.student.common.messagebuilder.impl;
002    
003    import java.util.ArrayList;
004    import java.util.List;
005    
006    import org.kuali.student.common.messagebuilder.booleanmessage.ast.BooleanNode;
007    import org.kuali.student.common.messagebuilder.impl.exceptions.MessageBuilderException;
008    
009    /**
010     * This class creates failure messages for boolean binary tree nodes.
011     */
012    public class FailureMessageBuilder {
013            /** Boolean operators to use in creating the failure message */
014            private BooleanOperators booleanOperators;
015    
016            /**
017             * Creates a failure message builder with boolean operators to use in 
018             * building the success message.
019             * 
020             * @param bo Boolean operators to build success message
021             */
022            public FailureMessageBuilder(BooleanOperators bo) {
023                    this.booleanOperators = bo;
024            }
025    
026            /**
027             * Builds and sets the failure message for each of the 
028             * boolean nodes (binary tree) in the <code>nodeList</code>.
029             * 
030             * @param nodeList List of boolean nodes
031             * @return Complete failure message 
032             */
033            public String buildFailureMessage(List<BooleanNode> nodeList) throws MessageBuilderException {
034                    // List must only contain one root node
035                    List<BooleanNode> rootNodeList = new ArrayList<BooleanNode>();
036                    for(BooleanNode node : nodeList) {
037                            if(node.getParent() == null) {
038                                    rootNodeList.add(node);
039                            }
040                            buildFailureMessage(node);
041                    }
042                    if(rootNodeList.size() > 1) {
043                            throw new MessageBuilderException("Node list contains more than one root node: " + rootNodeList);
044                    }
045                    return rootNodeList.get(0).getNodeMessage();
046            }
047    
048            /**
049             * Builds and sets the failure message for a single 
050             * boolean <code>node</code> (b-tree node).
051             * 
052             * @param node Boolean node
053             */
054            public String buildFailureMessage(BooleanNode node) {
055                    // OR
056                    if(node.getLabel().equals("+")){
057                            buildOrNodeFailureMessage(node);
058                    }
059                    // AND
060                    else if(node.getLabel().equals("*")) {
061                            buildAnd1NodeFailureMessage(node);
062                            buildAnd2NodeFailureMessage(node);
063                    }
064                    return node.getNodeMessage();
065            }
066    
067            /**
068             * Builds a failure message for an OR node (b-tree node).
069             * 
070             * @param node Boolean node
071             */
072            private void buildOrNodeFailureMessage(BooleanNode node) {
073                    // OR
074                    if(node.getLabel().equals("+") &&
075                                    node.getLeftNode() != null && 
076                                    node.getRightNode() != null &&
077                                    node.getLeftNode().getValue() == false && 
078                                    node.getRightNode().getValue() == false &&
079                                    node.getLeftNode().getNodeMessage() != null && 
080                                    node.getRightNode().getNodeMessage() != null) {
081                    String logMessage = node.getLeftNode().getNodeMessage() + " " + 
082                            this.booleanOperators.getOrOperator() + " " + 
083                            node.getRightNode().getNodeMessage();
084    
085                    if(node.getParent() != null && 
086                                            ( (node.getLabel().equals("+") && 
087                                                            node.getParent().getLabel().equals("*")) || 
088                                                            (node.getLabel().equals("*") && 
089                                                                            node.getParent().getLabel().equals("+")))) {
090                                logMessage = "(" + logMessage + ")";
091                            }
092                            node.setNodeMessage(logMessage);
093                    }
094            }
095    
096            /**
097             * Builds a failure message for an AND node (b-tree node) where 
098             * left node is true and right node is false or 
099             * left node is false and right node is true.
100             * 
101             * @param node Boolean node
102             */
103            private void buildAnd1NodeFailureMessage(BooleanNode node) {
104                    // AND1
105                    if(node.getLabel().equals("*") &&
106                                    node.getLeftNode() != null && 
107                                    node.getRightNode() != null &&
108                                    ((node.getLeftNode().getValue() == false && 
109                                                    node.getRightNode().getValue() == true && 
110                                                    node.getLeftNode().getNodeMessage() != null ) || 
111                                    (node.getLeftNode().getValue() == true && 
112                                                    node.getRightNode().getValue() == false && 
113                                                    node.getRightNode().getNodeMessage() != null))) {
114                            String logMessage = "test";
115                            
116                            if (node.getLeftNode().getValue() == false)
117                                    logMessage = node.getLeftNode().getNodeMessage();
118                            else if (node.getRightNode().getValue() == false)
119                                    logMessage = node.getRightNode().getNodeMessage();
120                            
121                            node.setNodeMessage(logMessage);
122                    }
123            }
124    
125            /**
126             * Builds a failure message for an AND node (b-tree node) where 
127             * left node and right node are false.
128             * 
129             * @param node Boolean node
130             */
131            private void buildAnd2NodeFailureMessage(BooleanNode node) {
132                    // AND2
133                    if(node.getLabel().equals("*") && 
134                                    node.getLeftNode() != null && 
135                                    node.getRightNode() != null &&
136                                    node.getLeftNode().getValue() == false && 
137                                    node.getRightNode().getValue() == false && 
138                                    node.getLeftNode().getNodeMessage() != null && 
139                                    node.getRightNode().getNodeMessage() != null) {
140                    String logMessage = node.getLeftNode().getNodeMessage() + " " + 
141                            this.booleanOperators.getAndOperator() + " " + 
142                            node.getRightNode().getNodeMessage();
143                            
144                            if(node.getParent() != null && 
145                                            ( (node.getLabel().equals("+") && 
146                                                            node.getParent().getLabel().equals("*")) || 
147                                                            (node.getLabel().equals("*") && 
148                                                                            node.getParent().getLabel().equals("+")))) {
149                                logMessage = "(" + logMessage + ")";
150                            }
151                            node.setNodeMessage(logMessage);
152                    }
153            }
154    }