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