Coverage Report - org.kuali.student.core.statement.ui.client.widgets.rules.SubrulePreviewWidget
 
Classes in this File Line Coverage Branch Coverage Complexity
SubrulePreviewWidget
0%
0/113
0%
0/60
3.462
 
 1  
 package org.kuali.student.core.statement.ui.client.widgets.rules;
 2  
 
 3  
 import java.util.List;
 4  
 import java.util.Map;
 5  
 
 6  
 import org.kuali.student.common.ui.client.configurable.mvc.SectionTitle;
 7  
 import org.kuali.student.common.ui.client.widgets.KSButton;
 8  
 import org.kuali.student.common.ui.client.widgets.KSButtonAbstract.ButtonStyle;
 9  
 import org.kuali.student.common.ui.client.widgets.ULPanel;
 10  
 import org.kuali.student.common.ui.client.widgets.field.layout.element.SpanPanel;
 11  
 import org.kuali.student.core.statement.dto.ReqCompFieldInfo;
 12  
 import org.kuali.student.core.statement.dto.ReqComponentInfo;
 13  
 import org.kuali.student.core.statement.dto.StatementOperatorTypeKey;
 14  
 import org.kuali.student.core.statement.dto.StatementTreeViewInfo;
 15  
 
 16  
 import com.google.gwt.event.dom.client.ClickHandler;
 17  
 import com.google.gwt.user.client.ui.ComplexPanel;
 18  
 import com.google.gwt.user.client.ui.FlowPanel;
 19  
 import com.google.gwt.user.client.ui.HTML;
 20  
 import com.google.gwt.user.client.ui.Widget;
 21  
 
 22  
 public class SubrulePreviewWidget extends FlowPanel {
 23  
 
 24  
     private static final String OPERATOR_HEADER_OR = "Must meet 1 of the following:";
 25  
     private static final String OPERATOR_HEADER_AND = "Must meet all of the following:";
 26  
     private static final String SUBRULE_LI_CSS_CLASS = "KS-Rule-Preview-Subrule-li";
 27  
     private static final String SUBRULE_UL_CSS_CLASS = "KS-Program-Rule-Preview-Subrule-ul";
 28  0
     private KSButton editButton = new KSButton("Edit", ButtonStyle.DEFAULT_ANCHOR);
 29  0
     private SpanPanel separator = new SpanPanel(" | ");
 30  0
     private KSButton deleteButton = new KSButton("Delete", ButtonStyle.DEFAULT_ANCHOR);
 31  0
     private boolean isReadOnly = true;
 32  
     private Map<String, Widget> clusetWidgets;
 33  0
     private boolean flag = false;
 34  
 
 35  
     public SubrulePreviewWidget(StatementTreeViewInfo stmtTreeInfo, boolean isReadOnly, Map<String, Widget> clusetWidgets) {
 36  0
         super();
 37  0
         this.isReadOnly = isReadOnly;
 38  0
         this.clusetWidgets = clusetWidgets;
 39  
 
 40  0
         addStyleName("KS-Rule-Preview-Subrule-Box");
 41  0
         showSubrule(stmtTreeInfo);
 42  0
     }
 43  
 
 44  
     public void showSubrule(StatementTreeViewInfo stmtTreeInfo) {
 45  0
         this.clear();
 46  
 
 47  0
         if (stmtTreeInfo == null) {
 48  0
             return;
 49  
         }
 50  
 
 51  0
         buildRequirementHeader(stmtTreeInfo);
 52  0
         buildRequirement(stmtTreeInfo);
 53  0
     }
 54  
 
 55  
     private void buildRequirementHeader(StatementTreeViewInfo stmtTreeInfo) {
 56  
 
 57  0
         SectionTitle header = SectionTitle.generateH6Title("");
 58  0
         if (stmtTreeInfo.getOperator() == StatementOperatorTypeKey.AND) {
 59  0
             header.setHTML("Must meet <b>all of the following:</b>");
 60  
         } else {
 61  0
             header.setHTML("Must meet <b>1 of the following:</b>");
 62  
         }
 63  0
         header.setStyleName("KS-Rule-Preview-Subrule-header");
 64  0
         header.getElement().setAttribute("style", "font-weight: normal");
 65  
 
 66  
         //do not show edit,delete etc. if user is only viewing the rule in non-edit mode
 67  0
         if (!isReadOnly) {
 68  0
             buildEditActionsWidget(header);
 69  
         }
 70  0
         this.add(header);
 71  0
     }
 72  
 
 73  
     private void buildEditActionsWidget(SectionTitle header) {
 74  0
         SpanPanel actions = new SpanPanel();
 75  0
         actions.add(editButton);
 76  0
         actions.add(separator);
 77  0
         actions.add(deleteButton);
 78  0
         actions.addStyleName("KS-Rule-Preview-Subrule-header-action");
 79  0
         header.add(actions);
 80  0
     }
 81  
 
 82  
     private void buildRequirement(StatementTreeViewInfo stmtTreeInfo) {
 83  0
         Widget requirementsWidget = buildRequirementsWidget(stmtTreeInfo);
 84  
         
 85  0
         if(requirementsWidget != null) {
 86  0
             this.add(requirementsWidget);
 87  
         }
 88  0
     }
 89  
     
 90  
     /**
 91  
      * 
 92  
      * This method handles creating the requirements preview widget at the parent level.  Further sub-statements are 
 93  
      * handled with recursive calls of another method 
 94  
      * 
 95  
      * @param rootStatement
 96  
      * @return
 97  
      */
 98  
     private ComplexPanel buildRequirementsWidget(StatementTreeViewInfo rootStatement) {
 99  0
         ULPanel statementBulletList = new ULPanel();
 100  0
         statementBulletList.setULClassName(SUBRULE_UL_CSS_CLASS);
 101  
         
 102  
         // handle simplest leaf case, where the statement has only requirement components
 103  0
         if(rootStatement.getReqComponents() != null && !rootStatement.getReqComponents().isEmpty()) {
 104  
             
 105  0
             populateRequirementComponentWidgets(rootStatement, statementBulletList);
 106  
             
 107  
         }
 108  
         else {
 109  
             // if no sub statements or requirement components, then return null, nothing to do
 110  0
             if(rootStatement.getStatements() == null || rootStatement.getStatements().isEmpty()) {
 111  0
                 return null;
 112  
             }
 113  
             
 114  
             // statement has sub-statements, so prepare for recursion
 115  0
             boolean firstInList = true;
 116  0
             for(StatementTreeViewInfo subStatement : rootStatement.getStatements()) {
 117  
                 
 118  0
                 statementBulletList.add(buildSubStatementWidget(subStatement, rootStatement, firstInList));
 119  0
                 firstInList = false;
 120  
             }
 121  
             
 122  
         }
 123  
         
 124  
         
 125  
         
 126  0
         return statementBulletList;
 127  
     }
 128  
 
 129  
     /**
 130  
      * 
 131  
      * This method adds LI elements to the provided ULPanel.  Each element consists of the panel 
 132  
      * returned by buildRequirementPanel using each RequirementComponentInfo found in the provided 
 133  
      * StatementTreeViewInfo
 134  
      * 
 135  
      * @param statement
 136  
      * @param list
 137  
      */
 138  
     private void populateRequirementComponentWidgets(StatementTreeViewInfo statement, ULPanel list) {
 139  0
         StatementOperatorTypeKey includedOperator = null;
 140  0
         for (ReqComponentInfo reqComp : statement.getReqComponents()) {
 141  0
             String nl = getPreviewNaturalLanguageForReqComponent(reqComp);
 142  
             
 143  0
             list.add(buildRequirementPanel(reqComp, includedOperator, nl), SUBRULE_LI_CSS_CLASS);
 144  
             
 145  
             // only pass the operator after the first requirement panel is built
 146  0
             if(includedOperator == null) {
 147  0
                 includedOperator = statement.getOperator();
 148  
             }
 149  0
         }
 150  0
     }
 151  
 
 152  
     /**
 153  
      * 
 154  
      * This method is called recursively to return a preview widget for the data in subStatement
 155  
      * 
 156  
      * @param subStatement
 157  
      * @param parentStatement 
 158  
      * @param firstInList flag to indicate that this statement is the first of its siblings, and does not need to start with the operator keyword
 159  
      * 
 160  
      * @return
 161  
      */
 162  
     private Widget buildSubStatementWidget(StatementTreeViewInfo subStatement, StatementTreeViewInfo parentStatement, boolean firstInList) {
 163  
         //flag = false;
 164  0
         StatementOperatorTypeKey prefixOperator = null;
 165  0
         if(!firstInList) {
 166  0
             prefixOperator = subStatement.getOperator();
 167  
         }
 168  
         
 169  0
         boolean hasReqComponents = (subStatement.getReqComponents() != null && !subStatement.getReqComponents().isEmpty());
 170  
         
 171  
         // simplest case:  statement has one requisite component and its operator is the same as its parent
 172  0
         if(hasReqComponents && subStatement.getReqComponents().size() == 1 && subStatement.getOperator() == parentStatement.getOperator()) {
 173  
             // return requirement component text, including operator text if applicable
 174  0
             ReqComponentInfo reqComp = subStatement.getReqComponents().iterator().next();
 175  0
             String nl = getPreviewNaturalLanguageForReqComponent(reqComp);
 176  0
             flag = true;
 177  0
             return buildRequirementPanel(reqComp, prefixOperator, nl);
 178  
           }
 179  
         
 180  
         // The statement has one or more requisite components or sub-statements, so build the header text
 181  0
         StringBuilder headerText = new StringBuilder();
 182  
         
 183  0
         if (flag == true) {
 184  0
             prefixOperator = parentStatement.getOperator();
 185  0
             flag = false;
 186  
         }
 187  0
         appendOperatorTag(headerText, prefixOperator);
 188  
         
 189  0
         headerText.append(subStatement.getOperator() == StatementOperatorTypeKey.AND ? OPERATOR_HEADER_AND : OPERATOR_HEADER_OR);
 190  
         
 191  0
         FlowPanel panel = new FlowPanel();
 192  0
         panel.add(new HTML(headerText.toString()));
 193  
         
 194  0
         if(hasReqComponents) {
 195  
             // requisite component case: a sub-statement with only requisite components
 196  0
             ULPanel subrulePanel = new ULPanel();
 197  0
             subrulePanel.setULClassName(SUBRULE_UL_CSS_CLASS);
 198  
             
 199  0
             populateRequirementComponentWidgets(subStatement, subrulePanel);
 200  
             
 201  0
             panel.add(subrulePanel);
 202  
             
 203  0
         }
 204  
         else {
 205  
             // sub-statement case: for each sub statement, call this method recursively
 206  0
             boolean firstInSubList = true;
 207  0
             for(StatementTreeViewInfo childStatement : subStatement.getStatements()) {
 208  0
                 panel.add(buildSubStatementWidget(childStatement, subStatement, firstInSubList));
 209  0
                 firstInSubList = false;
 210  
             }
 211  
             
 212  
         }
 213  
         
 214  0
         return panel;
 215  
     }
 216  
     
 217  
     private void appendOperatorTag(StringBuilder builder, StatementOperatorTypeKey operator) {
 218  0
         if(operator != null && builder != null) {
 219  0
             builder.append("<span class=\"KS-Program-Rule-Preview-Subrule-ORAND\">").append(operator.toString()).append(" ").append("</span>");
 220  
         }
 221  0
     }
 222  
 
 223  
     private String getPreviewNaturalLanguageForReqComponent(ReqComponentInfo reqComp) {
 224  0
         String nl = null;
 225  0
         if (reqComp instanceof ReqComponentInfoUi) {
 226  0
             nl = ((ReqComponentInfoUi)reqComp).getPreviewNaturalLanguageTranslation();
 227  
         }
 228  0
         if ( nl == null) {
 229  0
             nl = reqComp.getNaturalLanguageTranslation();
 230  
         }
 231  0
         return nl;
 232  
     }
 233  
     
 234  
     private FlowPanel buildRequirementPanel(ReqComponentInfo reqComp, StatementOperatorTypeKey operator, String requirement) {
 235  
         
 236  0
         FlowPanel requirementPanel = new FlowPanel();
 237  
         
 238  0
         StringBuilder htmlBuilder = new StringBuilder();
 239  0
         appendOperatorTag(htmlBuilder, operator);
 240  0
         htmlBuilder.append(requirement);
 241  
         
 242  0
         requirementPanel.add(new HTML(htmlBuilder.toString()));
 243  
 
 244  
         //we need to display clu set show/hide list widget if this req. component has a cluset
 245  0
         if ((clusetWidgets != null) && (reqComp != null)) {
 246  0
             List<ReqCompFieldInfo> fieldInfos = reqComp.getReqCompFields();
 247  0
             for (ReqCompFieldInfo fieldInfo : fieldInfos) {
 248  0
                 if (RulesUtil.isCluSetWidget(fieldInfo.getType())) {
 249  0
                     Widget csWidget = clusetWidgets.get(fieldInfo.getValue());
 250  0
                     if (csWidget != null) {
 251  0
                         requirementPanel.add(csWidget);
 252  0
                         break;
 253  
                     }
 254  0
                 }
 255  
             }
 256  
         }
 257  
 
 258  0
         return requirementPanel;
 259  
     }
 260  
 
 261  
     public void addEditButtonClickHandler(ClickHandler handler) {
 262  0
         editButton.addClickHandler(handler);
 263  0
     }
 264  
 
 265  
     public void addDeleteButtonClickHandler(ClickHandler handler) {
 266  0
         deleteButton.addClickHandler(handler);
 267  0
     }
 268  
 }