Coverage Report - org.kuali.student.lum.program.client.requirements.ProgramRequirementsSummaryView
 
Classes in this File Line Coverage Branch Coverage Complexity
ProgramRequirementsSummaryView
0%
0/230
0%
0/76
2.021
ProgramRequirementsSummaryView$1
0%
0/5
0%
0/2
2.021
ProgramRequirementsSummaryView$10
0%
0/7
0%
0/4
2.021
ProgramRequirementsSummaryView$10$1
0%
0/6
0%
0/2
2.021
ProgramRequirementsSummaryView$11
0%
0/15
0%
0/4
2.021
ProgramRequirementsSummaryView$11$1
0%
0/3
N/A
2.021
ProgramRequirementsSummaryView$11$2
0%
0/9
N/A
2.021
ProgramRequirementsSummaryView$12
0%
0/3
N/A
2.021
ProgramRequirementsSummaryView$13
0%
0/5
0%
0/2
2.021
ProgramRequirementsSummaryView$2
0%
0/5
0%
0/2
2.021
ProgramRequirementsSummaryView$3
0%
0/3
N/A
2.021
ProgramRequirementsSummaryView$4
0%
0/3
N/A
2.021
ProgramRequirementsSummaryView$5
0%
0/3
N/A
2.021
ProgramRequirementsSummaryView$6
0%
0/5
N/A
2.021
ProgramRequirementsSummaryView$6$1
0%
0/6
N/A
2.021
ProgramRequirementsSummaryView$7
0%
0/9
N/A
2.021
ProgramRequirementsSummaryView$7$1
0%
0/4
N/A
2.021
ProgramRequirementsSummaryView$8
0%
0/3
N/A
2.021
ProgramRequirementsSummaryView$8$1
0%
0/4
N/A
2.021
ProgramRequirementsSummaryView$9
0%
0/3
N/A
2.021
ProgramRequirementsSummaryView$ProgramReqDialogView
0%
0/2
N/A
2.021
 
 1  
 package org.kuali.student.lum.program.client.requirements;
 2  
 
 3  
 import com.google.gwt.core.client.GWT;
 4  
 import com.google.gwt.event.dom.client.ClickEvent;
 5  
 import com.google.gwt.event.dom.client.ClickHandler;
 6  
 import com.google.gwt.event.shared.HandlerManager;
 7  
 import com.google.gwt.user.client.Window;
 8  
 import com.google.gwt.user.client.ui.FlowPanel;
 9  
 import com.google.gwt.user.client.ui.Widget;
 10  
 
 11  
 import org.kuali.student.common.assembly.data.ConstraintMetadata;
 12  
 import org.kuali.student.common.assembly.data.Data;
 13  
 import org.kuali.student.common.assembly.data.Metadata;
 14  
 import org.kuali.student.common.assembly.data.QueryPath;
 15  
 import org.kuali.student.common.dto.RichTextInfo;
 16  
 import org.kuali.student.common.ui.client.application.Application;
 17  
 import org.kuali.student.common.ui.client.application.KSAsyncCallback;
 18  
 import org.kuali.student.common.ui.client.configurable.mvc.FieldDescriptor;
 19  
 import org.kuali.student.common.ui.client.configurable.mvc.SectionTitle;
 20  
 import org.kuali.student.common.ui.client.configurable.mvc.layouts.BasicLayout;
 21  
 import org.kuali.student.common.ui.client.configurable.mvc.sections.GroupSection;
 22  
 import org.kuali.student.common.ui.client.configurable.mvc.views.VerticalSectionView;
 23  
 import org.kuali.student.common.ui.client.mvc.*;
 24  
 import org.kuali.student.common.ui.client.service.MetadataRpcService;
 25  
 import org.kuali.student.common.ui.client.service.MetadataRpcServiceAsync;
 26  
 import org.kuali.student.common.ui.client.widgets.KSButton;
 27  
 import org.kuali.student.common.ui.client.widgets.KSButtonAbstract;
 28  
 import org.kuali.student.common.ui.client.widgets.KSLabel;
 29  
 import org.kuali.student.common.ui.client.widgets.KSLightBox;
 30  
 import org.kuali.student.common.ui.client.widgets.buttongroups.ButtonEnumerations;
 31  
 import org.kuali.student.common.ui.client.widgets.dialog.ConfirmationDialog;
 32  
 import org.kuali.student.common.ui.client.widgets.field.layout.button.ActionCancelGroup;
 33  
 import org.kuali.student.common.ui.client.widgets.field.layout.element.MessageKeyInfo;
 34  
 import org.kuali.student.common.ui.client.widgets.field.layout.element.SpanPanel;
 35  
 import org.kuali.student.common.ui.client.widgets.progress.BlockingTask;
 36  
 import org.kuali.student.common.ui.client.widgets.progress.KSBlockingProgressIndicator;
 37  
 import org.kuali.student.common.validation.dto.ValidationResultInfo;
 38  
 import org.kuali.student.core.statement.dto.*;
 39  
 import org.kuali.student.core.statement.ui.client.widgets.rules.RulePreviewWidget;
 40  
 import org.kuali.student.core.statement.ui.client.widgets.rules.RulesUtil;
 41  
 import org.kuali.student.lum.common.client.widgets.CluSetDetailsWidget;
 42  
 import org.kuali.student.lum.common.client.widgets.CluSetRetriever;
 43  
 import org.kuali.student.lum.common.client.widgets.CluSetRetrieverImpl;
 44  
 import org.kuali.student.lum.program.client.ProgramConstants;
 45  
 import org.kuali.student.lum.program.client.ProgramSections;
 46  
 import org.kuali.student.lum.program.client.properties.ProgramProperties;
 47  
 import org.kuali.student.lum.program.client.widgets.EditableHeader;
 48  
 import org.kuali.student.lum.program.dto.ProgramRequirementInfo;
 49  
 
 50  
 import java.util.*;
 51  
 
 52  0
 public class ProgramRequirementsSummaryView extends VerticalSectionView {
 53  
 
 54  0
     private MetadataRpcServiceAsync metadataServiceAsync = GWT.create(MetadataRpcService.class);
 55  0
     private static CluSetRetriever cluSetRetriever = new CluSetRetrieverImpl();
 56  
 
 57  
     //view's widgets
 58  0
     private FlowPanel layout = new FlowPanel();
 59  0
     private ActionCancelGroup actionCancelButtons = new ActionCancelGroup(ButtonEnumerations.SaveCancelEnum.SAVE, ButtonEnumerations.SaveCancelEnum.CANCEL);
 60  
     private BasicLayout reqCompController;
 61  0
     private FlowPanel holdFieldsPanel = new FlowPanel();
 62  
 
 63  
     //view's data
 64  
     private ProgramRequirementsViewController parentController;
 65  
     private ProgramRequirementsDataModel rules;
 66  
     private boolean isReadOnly;
 67  
     
 68  0
     public static int tempStmtTreeID = 9999;
 69  
     public static final String NEW_PROG_REQ_ID = "NEWPROGREQ";
 70  
     public static final String NEW_STMT_TREE_ID = "NEWSTMTTREE";
 71  
     public static final String NEW_REQ_COMP_ID = "NEWREQCOMP";
 72  
 
 73  
 
 74  0
     private enum ProgramReqDialogView {
 75  0
         VIEW
 76  
     }
 77  
 
 78  
     private static final String PROG_REQ_MODEL_ID = "progReqModelId";
 79  
     private DataModel progReqData;
 80  0
     private BlockingTask gettingMetadataTask = new BlockingTask("Loading");
 81  0
     private static Metadata dialogMetadata = null;  //simple caching
 82  
 
 83  0
     private Map<String, SpanPanel> perProgramRequirementTypePanel = new LinkedHashMap<String, SpanPanel>();
 84  0
     private Map<String, KSLabel> perProgramRequirementTypeTotalCredits = new LinkedHashMap<String, KSLabel>();
 85  
 
 86  
     public ProgramRequirementsSummaryView(final ProgramRequirementsViewController parentController, HandlerManager eventBus, Enum<?> viewEnum, String name,
 87  
                                           String modelId, boolean isReadOnly) {
 88  0
         super(viewEnum, name, modelId);
 89  0
         init(parentController, eventBus, isReadOnly);
 90  0
     }
 91  
 
 92  
     public ProgramRequirementsSummaryView(final ProgramRequirementsViewController parentController, HandlerManager eventBus, Enum<?> viewEnum, String name,
 93  
                                           String modelId, boolean isReadOnly, EditableHeader header) {
 94  0
         super(viewEnum, name, modelId, header);
 95  0
         init(parentController, eventBus, isReadOnly);
 96  0
     }
 97  
 
 98  
     private void init(ProgramRequirementsViewController parentController, HandlerManager eventBus, boolean isReadOnly) {
 99  0
         this.parentController = parentController;
 100  0
         this.isReadOnly = isReadOnly;
 101  0
         rules = new ProgramRequirementsDataModel(eventBus);
 102  
 
 103  0
         if (!isReadOnly) {
 104  0
             setupSaveCancelButtons();
 105  
         }
 106  0
     }
 107  
 
 108  
     @Override
 109  
     public boolean isDirty() {
 110  0
         return rules.isDirty();
 111  
     }
 112  
 
 113  
     protected ProgramRequirementsDataModel getRules() {
 114  0
         return rules;
 115  
     }
 116  
 
 117  
     @Override
 118  
     public void beforeShow(final Callback<Boolean> onReadyCallback) {
 119  0
         if (!rules.isInitialized() || parentController.reloadFlag) {
 120  0
             retrieveProgramRequirements(onReadyCallback);
 121  0
             return;
 122  
         }
 123  0
         onReadyCallback.exec(true);
 124  0
     }
 125  
 
 126  
     private void retrieveProgramRequirements(final Callback<Boolean> onReadyCallback) {
 127  0
         rules.retrieveProgramRequirements(parentController, new Callback<Boolean>() {
 128  
             @Override
 129  
             public void exec(Boolean result) {
 130  0
                 if (result) {
 131  0
                     displayRules();
 132  
                 }
 133  0
                 onReadyCallback.exec(result);
 134  0
             }
 135  
         });
 136  0
     }
 137  
 
 138  
     public void storeRules(final Callback<Boolean> callback) {
 139  0
         rules.updateProgramEntities(new Callback<List<ProgramRequirementInfo>>() {
 140  
             @Override
 141  
             public void exec(List<ProgramRequirementInfo> programReqInfos) {
 142  0
                 for (ProgramRequirementInfo programReqInfo : programReqInfos) {
 143  0
                     updateRequirementWidgets(programReqInfo);
 144  
                 }
 145  0
                 callback.exec(true);
 146  0
             }
 147  
         });
 148  0
     }
 149  
 
 150  
      public void justStoreRules(final Callback<Boolean> callback) {
 151  0
         rules.updateProgramEntities(new Callback<List<ProgramRequirementInfo>>() {
 152  
             @Override
 153  
             public void exec(List<ProgramRequirementInfo> programReqInfos) {
 154  0
                 callback.exec(true);
 155  0
             }
 156  
         });
 157  0
     }
 158  
 
 159  
     public void revertRuleChanges() {
 160  0
         rules.revertRuleChanges();
 161  0
         displayRules();
 162  0
     }
 163  
 
 164  
     protected void updateRequirementWidgets(ProgramRequirementInfo programReqInfo) {
 165  0
         if (programReqInfo != null) {
 166  0
             StatementTypeInfo affectedStatementTypeInfo = rules.getStmtTypeInfo(programReqInfo.getStatement().getType());
 167  0
             SpanPanel reqPanel = perProgramRequirementTypePanel.get(affectedStatementTypeInfo.getId());
 168  
 
 169  
             //this happens if user previously deleted requirement but didn't save when moving to another section
 170  
             //add widget
 171  0
             if (reqPanel.getWidgetCount() == 0) {
 172  0
                 reqPanel.add(addProgramRequirement(reqPanel, programReqInfo));
 173  0
                 return;
 174  
             }
 175  
 
 176  
             //replace widget with a new version
 177  0
             for (int i = 0; i < reqPanel.getWidgetCount(); i++) {
 178  0
                 RulePreviewWidget rulePreviewWidget = (RulePreviewWidget) reqPanel.getWidget(i);
 179  0
                 if (rulePreviewWidget.getInternalProgReqID().equals(rules.getInternalProgReqID(programReqInfo))) {
 180  0
                     RulePreviewWidget newRulePreviewWidget = addProgramRequirement(reqPanel, programReqInfo);
 181  0
                     reqPanel.insert(newRulePreviewWidget, i);
 182  0
                     reqPanel.remove(rulePreviewWidget);
 183  0
                     break;
 184  
                 }
 185  
             }
 186  
         }
 187  0
     }
 188  
 
 189  
     public void displayRules() {
 190  0
         remove(layout);
 191  0
         layout.clear();
 192  
 
 193  
         //display 'Program Requirements' page title (don't add if read only because the section itself will display the title)
 194  0
         if (!isReadOnly) {
 195  0
             SectionTitle pageTitle = SectionTitle.generateH2Title(ProgramProperties.get().programRequirements_summaryViewPageTitle());
 196  
             //pageTitle.setStyleName("KS-Program-Requirements-Section-header");  //make the header orange
 197  0
             pageTitle.addStyleName("ks-layout-header");// change the header to green
 198  
 
 199  0
             layout.add(pageTitle);
 200  
         }
 201  
 
 202  
         //iterate and display rules for each Program Requirement type e.g. Entrance Requirements, Completion Requirements
 203  0
         Boolean firstRequirement = true;
 204  0
         perProgramRequirementTypePanel.clear();
 205  0
         for (StatementTypeInfo stmtTypeInfo : rules.getStmtTypes()) {
 206  
 
 207  
             //create and display one type of program requirement section
 208  0
             SpanPanel requirementsPanel = new SpanPanel();
 209  0
             perProgramRequirementTypePanel.put(stmtTypeInfo.getId(), requirementsPanel);
 210  0
             displayRequirementSectionForGivenType(requirementsPanel, stmtTypeInfo, firstRequirement);
 211  0
             updateTotalCreditPerType(stmtTypeInfo.getId());
 212  0
             firstRequirement = false;
 213  
 
 214  
             //now display each requirement for this Program Requirement type
 215  0
             for (ProgramRequirementInfo ruleInfo : rules.getProgReqInfo(stmtTypeInfo.getId())) {
 216  0
                 RulePreviewWidget rulePreviewWidget = addProgramRequirement(requirementsPanel, ruleInfo);
 217  0
                 requirementsPanel.add(rulePreviewWidget);
 218  0
             }
 219  0
         }
 220  
 
 221  
         //save and cancel buttons
 222  0
         if (!isReadOnly) {
 223  0
             layout.add(actionCancelButtons);
 224  
         }
 225  
 
 226  0
         addWidget(layout);
 227  0
     }
 228  
 
 229  
     private void displayRequirementSectionForGivenType(final SpanPanel requirementsPanel, final StatementTypeInfo stmtTypeInfo, boolean firstRequirement) {
 230  
 
 231  
         //display header for this Program Requirement type e.g. Entrance Requirements; make the header plural
 232  0
         SectionTitle title = SectionTitle.generateH3Title(stmtTypeInfo.getName());
 233  0
         title.setStyleName((firstRequirement ? "KS-Program-Requirements-Preview-Rule-Type-First-Header" : "KS-Program-Requirements-Preview-Rule-Type-Header"));
 234  0
         layout.add(title);
 235  
 
 236  
         //add Total Credits
 237  0
         KSLabel totalCredits = new KSLabel();
 238  0
         totalCredits.addStyleName("KS-Program-Requirements-Preview-Rule-Type-Credits");
 239  0
         perProgramRequirementTypeTotalCredits.put(stmtTypeInfo.getId(), totalCredits);
 240  0
         totalCredits.setVisible(false);
 241  0
         layout.add(totalCredits);
 242  
 
 243  
         //add rule description
 244  0
         if (!isReadOnly) {
 245  0
             KSLabel ruleTypeDesc = new KSLabel(stmtTypeInfo.getDescr());
 246  0
             ruleTypeDesc.addStyleName("KS-Program-Requirements-Preview-Rule-Type-Desc");
 247  0
             layout.add(ruleTypeDesc);
 248  
         }
 249  
 
 250  
         //display "Add Rule" button if user is in 'edit' mode
 251  0
         if (!isReadOnly) {
 252  0
             String addRuleLabel = ProgramProperties.get().programRequirements_summaryViewPageAddRule(stmtTypeInfo.getName());
 253  0
             KSButton addProgramReqBtn = new KSButton(addRuleLabel, KSButtonAbstract.ButtonStyle.FORM_SMALL);
 254  0
             addProgramReqBtn.addClickHandler(new ClickHandler() {
 255  
                 public void onClick(ClickEvent event) {
 256  0
                     showProgramRequirementDialog(requirementsPanel, stmtTypeInfo.getId(), null);
 257  0
                 }
 258  
             });
 259  0
             layout.add(addProgramReqBtn);
 260  
         }
 261  
 
 262  0
         layout.add(requirementsPanel);
 263  0
     }
 264  
 
 265  
     private RulePreviewWidget addProgramRequirement(final SpanPanel requirementsPanel, final ProgramRequirementInfo progReqInfo) {
 266  
 
 267  0
         Integer internalProgReqID = rules.getInternalProgReqID(progReqInfo);
 268  0
         String stmtTypeId = progReqInfo.getStatement().getType();
 269  
 
 270  0
         int minCredits = (progReqInfo.getMinCredits() == null ? 0 : progReqInfo.getMinCredits());
 271  0
         int maxCredits = (progReqInfo.getMaxCredits() == null ? 0 : progReqInfo.getMaxCredits());
 272  0
         String plainDesc = (progReqInfo.getDescr() == null ? "" : progReqInfo.getDescr().getPlain());
 273  0
         final RulePreviewWidget rulePreviewWidget = new RulePreviewWidget(internalProgReqID, progReqInfo.getShortTitle(),
 274  
                 getTotalCreditsString(minCredits, maxCredits),
 275  
                 plainDesc, progReqInfo.getStatement(),
 276  
                 isReadOnly, getCluSetWidgetList(progReqInfo.getStatement()));
 277  0
         addRulePreviewWidgetHandlers(requirementsPanel, rulePreviewWidget, stmtTypeId, internalProgReqID);
 278  0
         return rulePreviewWidget;
 279  
     }
 280  
 
 281  
     private void addRulePreviewWidgetHandlers(final SpanPanel requirementsPanel, final RulePreviewWidget rulePreviewWidget, final String stmtTypeId, final Integer internalProgReqID) {
 282  
 
 283  
         //PROGRAM REQUIREMENT handlers
 284  0
         rulePreviewWidget.addProgReqEditButtonClickHandler(new ClickHandler() {
 285  
             public void onClick(ClickEvent event) {
 286  0
                 showProgramRequirementDialog(requirementsPanel, stmtTypeId, internalProgReqID);
 287  0
             }
 288  
         });
 289  
 
 290  0
         rulePreviewWidget.addProgReqDeleteButtonClickHandler(new ClickHandler() {
 291  
             public void onClick(ClickEvent event) {
 292  0
                 final ConfirmationDialog dialog = new ConfirmationDialog(
 293  
                         ProgramProperties.get().programRequirements_summaryViewPageDeleteRequirementDialogTitle(),
 294  
                         ProgramProperties.get().programRequirements_summaryViewPageDeleteRequirementDialogMsg());
 295  
 
 296  0
                 dialog.getConfirmButton().addClickHandler(new ClickHandler() {
 297  
                     @Override
 298  
                     public void onClick(ClickEvent event) {
 299  0
                         rules.deleteRule(internalProgReqID);
 300  
 
 301  
                         //remove rule from display
 302  0
                         requirementsPanel.remove(rulePreviewWidget);
 303  0
                         perProgramRequirementTypeTotalCredits.get(stmtTypeId).setVisible(false);
 304  0
                         dialog.hide();
 305  0
                     }
 306  
                 });
 307  0
                 dialog.show();
 308  0
             }
 309  
         });
 310  
 
 311  
         //SUBRULE handlers
 312  0
         rulePreviewWidget.addSubRuleAddButtonClickHandler(new ClickHandler() {
 313  
             public void onClick(ClickEvent event) {
 314  0
                 final StatementTreeViewInfo newSubRule = new StatementTreeViewInfo();
 315  0
                 newSubRule.setId(generateStatementTreeId());
 316  0
                 newSubRule.setType(stmtTypeId);
 317  0
                 RichTextInfo text = new RichTextInfo();
 318  0
                 text.setPlain("");
 319  0
                 newSubRule.setDesc(text);
 320  0
                 parentController.getView(ProgramRequirementsViewController.ProgramRequirementsViews.MANAGE, new Callback<View>() {
 321  
 
 322  
                     @Override
 323  
                     public void exec(View result) {
 324  0
                         ((ProgramRequirementsManageView) result).setRuleTree(newSubRule, true, internalProgReqID);
 325  0
                         parentController.showView(ProgramRequirementsViewController.ProgramRequirementsViews.MANAGE);
 326  0
                     }
 327  
                 });
 328  0
             }
 329  
         });
 330  
 
 331  0
         rulePreviewWidget.addSubRuleEditButtonClickHandler(new Callback<RulePreviewWidget.SubRuleInfo>() {
 332  
             public void exec(final RulePreviewWidget.SubRuleInfo subRuleInfo) {
 333  0
                 parentController.getView(ProgramRequirementsViewController.ProgramRequirementsViews.MANAGE, new Callback<View>() {
 334  
                     @Override
 335  
                     public void exec(View result) {
 336  0
                         ((ProgramRequirementsManageView) result).setRuleTree(subRuleInfo.getSubrule(), false, subRuleInfo.getInternalProgReqID());
 337  0
                         parentController.showView(ProgramRequirementsViewController.ProgramRequirementsViews.MANAGE);
 338  0
                     }
 339  
                 });
 340  0
             }
 341  
         });
 342  
 
 343  0
         rulePreviewWidget.addSubRuleDeleteCallback(new Callback<Integer>() {
 344  
             public void exec(final Integer internalProgReqID) {
 345  
                 //deleting subrule does not delete the requirement (rule) itself
 346  0
                 rules.markRuleAsEdited(internalProgReqID);
 347  0
             }
 348  
         });
 349  0
     }
 350  
 
 351  
     protected Map<String, Widget> getCluSetWidgetList(StatementTreeViewInfo rule) {
 352  0
         Map<String, Widget> widgetList = new HashMap<String, Widget>();
 353  0
         Set<String> cluSetIds = new HashSet<String>();
 354  0
         findCluSetIds(rule, cluSetIds);
 355  0
         for (String clusetId : cluSetIds) {
 356  0
             widgetList.put(clusetId, new CluSetDetailsWidget(clusetId, cluSetRetriever));
 357  
         }
 358  
 
 359  0
         return widgetList;
 360  
     }
 361  
 
 362  
     private void findCluSetIds(StatementTreeViewInfo rule, Set<String> list) {
 363  
 
 364  0
         List<StatementTreeViewInfo> statements = rule.getStatements();
 365  0
         List<ReqComponentInfo> reqComponentInfos = rule.getReqComponents();
 366  
 
 367  0
         if ((statements != null) && (statements.size() > 0)) {
 368  
             // retrieve all statements
 369  0
             for (StatementTreeViewInfo statement : statements) {
 370  0
                 findCluSetIds(statement, list); // inside set the children of this statementTreeViewInfo
 371  
             }
 372  0
         } else if ((reqComponentInfos != null) && (reqComponentInfos.size() > 0)) {
 373  
             // retrieve all req. component LEAFS
 374  0
             for (ReqComponentInfo reqComponent : reqComponentInfos) {
 375  0
                 List<ReqCompFieldInfo> fieldInfos = reqComponent.getReqCompFields();
 376  0
                 for (ReqCompFieldInfo fieldInfo : fieldInfos) {
 377  0
                     if (RulesUtil.isCluSetWidget(fieldInfo.getType())) {
 378  0
                         list.add(fieldInfo.getValue());
 379  
                     }
 380  
                 }
 381  0
             }
 382  
         }
 383  0
     }
 384  
 
 385  
     private void showProgramRequirementDialog(final SpanPanel requirementsPanel, final String stmtTypeId, final Integer internalProgReqID) {
 386  
 
 387  0
         boolean isAddProgReq = (internalProgReqID == null);
 388  
 
 389  0
         String addRuleText = (isAddProgReq ? ProgramProperties.get().programRequirements_summaryViewPageAddRule(rules.getStmtTypeName(stmtTypeId)) : "Edit " + rules.getStmtTypeName(stmtTypeId));
 390  0
         final KSLightBox dialog = new KSLightBox(addRuleText);
 391  
 
 392  0
         final ButtonEnumerations.ButtonEnum actionButton = (isAddProgReq ? ButtonEnumerations.AddCancelEnum.ADD : ButtonEnumerations.UpdateCancelEnum.UPDATE);
 393  0
         ActionCancelGroup actionCancelButtons = new ActionCancelGroup(actionButton, ButtonEnumerations.UpdateCancelEnum.CANCEL);
 394  
 
 395  0
         actionCancelButtons.addCallback(new Callback<ButtonEnumerations.ButtonEnum>() {
 396  
             @Override
 397  
             public void exec(ButtonEnumerations.ButtonEnum result) {
 398  0
                 if (result == actionButton) {
 399  
 
 400  0
                     reqCompController.updateModel();
 401  
 
 402  
                     //validate and retrieve fields
 403  0
                     if (progReqData.getRoot().size() > 0) {
 404  0
                         progReqData.validate(new Callback<List<ValidationResultInfo>>() {
 405  
                             @Override
 406  
                             public void exec(List<ValidationResultInfo> validationResults) {
 407  
 
 408  
                                 //do not proceed if the user input is not valid
 409  0
                                 if (!reqCompController.isValid(validationResults, true, true)) {
 410  0
                                     return;
 411  
                                 }
 412  
 
 413  
                                 //retrieve entered values and set the rule info
 414  0
                                 updateProgramInfo(requirementsPanel, stmtTypeId, internalProgReqID);
 415  0
                                 dialog.hide();
 416  0
                             }
 417  
                         });
 418  
                     }
 419  
                 } else {
 420  0
                     dialog.hide();
 421  
                 }
 422  0
             }
 423  
         });
 424  
 
 425  0
         createAddProgramReqDialog(dialog, actionCancelButtons, internalProgReqID);
 426  0
     }
 427  
 
 428  
     private void createAddProgramReqDialog(final KSLightBox dialog, final ActionCancelGroup actionCancelButtons, final Integer internalProgReqID) {
 429  
 
 430  0
         parentController.requestModel(ProgramConstants.PROGRAM_MODEL_ID, new ModelRequestCallback<DataModel>() {
 431  
 
 432  
             @Override
 433  
             public void onRequestFail(Throwable cause) {
 434  0
                 Window.alert(cause.getMessage());
 435  0
                 GWT.log("Unable to retrieve program model for program summary view", cause);
 436  0
             }
 437  
 
 438  
             @Override
 439  
             public void onModelReady(DataModel model) {
 440  
 
 441  
                 //program has to be in the database before we can save program requirements
 442  0
                 String programId = model.getRoot().get(ProgramConstants.ID);
 443  0
                 if (programId == null) {
 444  0
                     final ConfirmationDialog dialog = new ConfirmationDialog("Save Program Key Info", "Before saving rules please save program key info");
 445  0
                     dialog.getConfirmButton().addClickHandler(new ClickHandler() {
 446  
                         @Override
 447  
                         public void onClick(ClickEvent event) {
 448  0
                             dialog.hide();
 449  0
                         }
 450  
                     });
 451  0
                     dialog.show();
 452  0
                     return;
 453  
                 }
 454  
 
 455  0
                 if (dialogMetadata == null) {
 456  0
                     KSBlockingProgressIndicator.addTask(gettingMetadataTask);
 457  0
                     metadataServiceAsync.getMetadataList("org.kuali.student.lum.program.dto.ProgramRequirementInfo", "Active", new KSAsyncCallback<Metadata>() {
 458  
                         public void handleFailure(Throwable caught) {
 459  0
                             KSBlockingProgressIndicator.removeTask(gettingMetadataTask);
 460  0
                             Window.alert(caught.getMessage());
 461  0
                             GWT.log("getMetadataList failed for ProgramRequirementInfo", caught);
 462  0
                         }
 463  
 
 464  
                         public void onSuccess(final Metadata metadata) {
 465  0
                             KSBlockingProgressIndicator.removeTask(gettingMetadataTask);
 466  0
                             dialogMetadata = metadata;
 467  0
                             showDialog(dialog, actionCancelButtons, metadata, internalProgReqID);
 468  0
                         }
 469  
                     });
 470  
                 } else {
 471  0
                     showDialog(dialog, actionCancelButtons, dialogMetadata, internalProgReqID);
 472  
                 }
 473  
 
 474  0
             }
 475  
         });
 476  0
     }
 477  
 
 478  
     private static FieldDescriptor createInputField(final String id, final Metadata metadata, final Map<String, Metadata> fieldDefinitionMetadata, final Map<String, FieldDescriptor> fields) {
 479  0
         FieldDescriptor fd = new FieldDescriptor(id, new MessageKeyInfo("program", "program", "draft", id), metadata);
 480  0
         fields.put(id, fd);
 481  
 
 482  
         //add field to the data model metadata
 483  0
         fieldDefinitionMetadata.put(id, metadata);
 484  
 
 485  0
         return fd;
 486  
     }
 487  
 
 488  
     //TODO rework to use Configurer if possible
 489  
     private void showDialog(final KSLightBox dialog, final ActionCancelGroup actionCancelButtons, Metadata metadata, Integer internalProgReqID) {
 490  
 
 491  0
         Map<String, Metadata> fieldDefinitionMetadata = new HashMap<String, Metadata>();
 492  0
         Map<String, FieldDescriptor> fields = new HashMap<String, FieldDescriptor>();
 493  0
         VerticalSectionView dialogPanel = new VerticalSectionView(ProgramReqDialogView.VIEW, "", PROG_REQ_MODEL_ID, false);
 494  0
         holdFieldsPanel.clear();
 495  
 
 496  0
         dialogPanel.addField(createInputField("shortTitle", metadata.getProperties().get("shortTitle"), fieldDefinitionMetadata, fields));
 497  0
         FieldDescriptor minFd = createInputField("minCredits", metadata.getProperties().get("minCredits"), fieldDefinitionMetadata, fields);
 498  0
         FieldDescriptor maxFd = createInputField("maxCredits", metadata.getProperties().get("maxCredits"), fieldDefinitionMetadata, fields);
 499  0
         GroupSection credits = new GroupSection();
 500  0
         credits.addField(minFd);
 501  0
         credits.addField(maxFd);
 502  0
         dialogPanel.addSection(credits);
 503  0
         final Metadata descrMetadata = metadata.getProperties().get("descr").getProperties().get("plain");
 504  0
         dialogPanel.addField(createInputField("descr", descrMetadata, fieldDefinitionMetadata, fields));
 505  
 
 506  0
         List<ConstraintMetadata> constraints = descrMetadata.getConstraints();
 507  0
         dialogPanel.addWidget(new KSLabel(constraints.get(0).getMaxLength() + getUILabel("descrLimit")));
 508  
 
 509  
         //setup data model
 510  0
         Metadata modelDefinitionMetadata = new Metadata();
 511  0
         modelDefinitionMetadata.setCanView(true);
 512  0
         modelDefinitionMetadata.setDataType(Data.DataType.DATA);
 513  0
         modelDefinitionMetadata.setProperties(fieldDefinitionMetadata);
 514  0
         progReqData = new DataModel();
 515  0
         progReqData.setRoot(new Data());
 516  0
         progReqData.setDefinition(new DataModelDefinition(modelDefinitionMetadata));
 517  
 
 518  
         //initialize fields with values if user is editing an existing rule
 519  0
         if (internalProgReqID != null) {
 520  0
             ProgramRequirementInfo progReq = rules.getProgReqByInternalId(internalProgReqID);
 521  0
             progReqData.set(QueryPath.parse("shortTitle"), progReq.getShortTitle());
 522  0
             progReqData.set(QueryPath.parse("minCredits"), progReq.getMinCredits());
 523  0
             progReqData.set(QueryPath.parse("maxCredits"), progReq.getMaxCredits());
 524  0
             progReqData.set(QueryPath.parse("descr"), (progReq.getDescr() == null ? "" : progReq.getDescr().getPlain()));
 525  
         }
 526  
 
 527  
         //setup controller
 528  0
         reqCompController = new BasicLayout(null);
 529  0
         reqCompController.addView(dialogPanel);
 530  0
         reqCompController.setDefaultModelId(PROG_REQ_MODEL_ID);
 531  0
         reqCompController.registerModel(PROG_REQ_MODEL_ID, new ModelProvider<DataModel>() {
 532  
             @Override
 533  
             public void requestModel(final ModelRequestCallback<DataModel> callback) {
 534  0
                 callback.onModelReady(progReqData);
 535  0
             }
 536  
         });
 537  
 
 538  
         //show fields
 539  0
         holdFieldsPanel.add(reqCompController);
 540  0
         reqCompController.showView(ProgramReqDialogView.VIEW);
 541  
 
 542  
         //layout.addStyleName("KS-Advanced-Search-Window");
 543  0
         holdFieldsPanel.add(actionCancelButtons);
 544  0
         dialog.setSize(550, 530);
 545  0
         dialog.setWidget(holdFieldsPanel);
 546  0
         dialog.show();
 547  0
     }
 548  
 
 549  
     private String getUILabel(final String id) {
 550  0
         return Application.getApplicationContext().getUILabel("program", null, null, id);
 551  
     }
 552  
 
 553  
     private void updateProgramInfo(SpanPanel requirementsPanel, String stmtTypeId, Integer internalProgReqID) {
 554  
 
 555  
         ProgramRequirementInfo progReqInfo;
 556  0
         if (internalProgReqID == null) {
 557  0
             progReqInfo = new ProgramRequirementInfo();
 558  0
             progReqInfo.setId(NEW_PROG_REQ_ID + Integer.toString(tempStmtTreeID++));   //set unique id
 559  0
             progReqInfo.setType("kuali.lu.type.Requirement");
 560  
 
 561  
             //create a top level statement tree
 562  0
             StatementTreeViewInfo stmtTree = new StatementTreeViewInfo();
 563  0
             stmtTree.setId(generateStatementTreeId());
 564  0
             stmtTree.setType(stmtTypeId);
 565  0
             RichTextInfo text2 = new RichTextInfo();
 566  0
             text2.setPlain("");
 567  0
             stmtTree.setDesc(text2);
 568  0
             stmtTree.setOperator(StatementOperatorTypeKey.AND); //AND is top level operator for rules within a Program Requirement
 569  
 
 570  
             //add new statement to the rule because even if user cancel on rule manage screen, we want to have at least one statement present
 571  0
             progReqInfo.setStatement(stmtTree);
 572  0
         } else {
 573  0
             progReqInfo = rules.getProgReqByInternalId(internalProgReqID);
 574  
         }
 575  
 
 576  0
         RichTextInfo text = new RichTextInfo();
 577  0
         text.setPlain((String) (progReqData.getRoot().get("descr")));
 578  0
         progReqInfo.setDescr(text);
 579  0
         progReqInfo.setShortTitle((String) progReqData.getRoot().get("shortTitle"));
 580  0
         progReqInfo.setLongTitle((String) progReqData.getRoot().get("shortTitle"));
 581  0
         progReqInfo.setMinCredits((Integer) progReqData.getRoot().get("minCredits"));
 582  0
         progReqInfo.setMaxCredits((Integer) progReqData.getRoot().get("maxCredits"));
 583  
 
 584  0
         if (internalProgReqID == null) {
 585  0
             rules.addRule(progReqInfo);
 586  0
             RulePreviewWidget rulePreviewWidget = addProgramRequirement(requirementsPanel, progReqInfo);
 587  0
             requirementsPanel.add(rulePreviewWidget);
 588  0
         } else {
 589  0
             rules.updateRule(internalProgReqID, progReqInfo);
 590  0
             for (Object aRequirementsPanel : requirementsPanel) {
 591  0
                 RulePreviewWidget rulePreviewWidget = (RulePreviewWidget) aRequirementsPanel;
 592  0
                 if (rulePreviewWidget.getInternalProgReqID().equals(internalProgReqID)) {
 593  0
                     rulePreviewWidget.updateProgInfoFields(progReqInfo.getShortTitle(),
 594  
                             getTotalCreditsString(progReqInfo.getMinCredits(), progReqInfo.getMaxCredits()),
 595  
                             progReqInfo.getDescr().getPlain());
 596  
                 }
 597  0
             }
 598  
         }
 599  
 
 600  0
         updateTotalCreditPerType(stmtTypeId);
 601  0
     }
 602  
 
 603  
     private String getTotalCreditsString(int min, int max) {
 604  0
         return "Expected Total Credits:" + min + "-" + max;
 605  
     }
 606  
 
 607  
     private void updateTotalCreditPerType(String stmtTypeId) {
 608  0
         int min = 0;
 609  0
         int max = 0;
 610  0
         for (ProgramRequirementInfo ruleInfo : rules.getProgReqInfo(stmtTypeId)) {
 611  0
             min += ruleInfo.getMinCredits();
 612  0
             max += ruleInfo.getMaxCredits();
 613  
         }
 614  
 
 615  0
         if (min != 0 || max != 0) {
 616  
             //update total
 617  0
             perProgramRequirementTypeTotalCredits.get(stmtTypeId).setVisible(true);
 618  0
             perProgramRequirementTypeTotalCredits.get(stmtTypeId).setText(getTotalCreditsString(min, max));
 619  
         }
 620  0
     }
 621  
 
 622  
     private void setupSaveCancelButtons() {
 623  0
         actionCancelButtons.addStyleName("KS-Program-Requirements-Save-Button");
 624  0
         actionCancelButtons.addCallback(new Callback<ButtonEnumerations.ButtonEnum>() {
 625  
             @Override
 626  
             public void exec(ButtonEnumerations.ButtonEnum result) {
 627  0
                 if (result == ButtonEnumerations.SaveCancelEnum.SAVE) {
 628  0
                     storeRules(Controller.NO_OP_CALLBACK);
 629  
                 } else {
 630  
                     //does not work any more: HistoryManager.navigate(AppLocations.Locations.VIEW_PROGRAM.getLocation(), parentController.getViewContext());
 631  0
                     parentController.getParentController().showView(ProgramSections.SUMMARY);
 632  
                 }
 633  0
             }
 634  
         });
 635  0
     }
 636  
 
 637  
     static public String generateStatementTreeId() {
 638  0
         return (NEW_STMT_TREE_ID + Integer.toString(tempStmtTreeID++));
 639  
     }
 640  
 }