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