View Javadoc

1   /**
2    * Copyright 2005-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krms.controller;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.core.api.util.tree.Node;
20  import org.kuali.rice.krad.uif.UifParameters;
21  import org.kuali.rice.krad.util.GlobalVariables;
22  import org.kuali.rice.krad.web.controller.MaintenanceDocumentController;
23  import org.kuali.rice.krad.web.form.MaintenanceDocumentForm;
24  import org.kuali.rice.krad.web.form.UifFormBase;
25  import org.kuali.rice.krms.api.repository.proposition.PropositionType;
26  import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition;
27  import org.kuali.rice.krms.dto.AgendaEditor;
28  import org.kuali.rice.krms.dto.PropositionEditor;
29  import org.kuali.rice.krms.dto.RuleEditor;
30  import org.kuali.rice.krms.dto.RuleManagementWrapper;
31  import org.kuali.rice.krms.impl.repository.KrmsRepositoryServiceLocator;
32  import org.kuali.rice.krms.service.RuleViewHelperService;
33  import org.kuali.rice.krms.util.AgendaUtilities;
34  import org.kuali.rice.krms.tree.node.SimplePropositionEditNode;
35  import org.kuali.rice.krms.tree.node.SimplePropositionNode;
36  import org.kuali.rice.krms.tree.node.RuleEditorTreeNode;
37  import org.kuali.rice.krms.util.KRMSConstants;
38  import org.kuali.rice.krms.util.PropositionTreeUtil;
39  import org.kuali.rice.krms.util.RuleLogicExpressionParser;
40  import org.kuali.student.common.uif.util.KSControllerHelper;
41  import org.springframework.validation.BindingResult;
42  import org.springframework.web.bind.annotation.ModelAttribute;
43  import org.springframework.web.bind.annotation.RequestMapping;
44  import org.springframework.web.servlet.ModelAndView;
45  
46  import javax.servlet.http.HttpServletRequest;
47  import javax.servlet.http.HttpServletResponse;
48  import java.util.ArrayList;
49  import java.util.List;
50  import java.util.Map;
51  
52  /**
53   * Controller for the KS KRMS page.
54   *
55   * @author Kuali Student Team
56   */
57  public class RuleEditorController extends MaintenanceDocumentController {
58  
59      /**
60       * Method used to invoke the CO inquiry view from Manage Course Offering screen while search input is Course Offering
61       * Code (04a screen)
62       *
63       * @param form
64       * @param result
65       * @param request
66       * @param response
67       * @return
68       */
69      @RequestMapping(params = "methodToCall=goToRuleView")
70      public ModelAndView goToRuleView(@ModelAttribute("KualiForm") UifFormBase form, @SuppressWarnings("unused") BindingResult result,
71                                       @SuppressWarnings("unused") HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) {
72  
73          //Clear the client state on new edit rule.
74          form.getClientStateForSyncing().clear();
75  
76          RuleEditor ruleEditor = AgendaUtilities.retrieveSelectedRuleEditor((MaintenanceDocumentForm) form);
77          this.getViewHelper(form).refreshInitTrees(ruleEditor);
78  
79          if (!form.getActionParameters().containsKey(UifParameters.NAVIGATE_TO_PAGE_ID)) {
80              form.getActionParameters().put(UifParameters.NAVIGATE_TO_PAGE_ID, KRMSConstants.KRMS_RULE_MAINTENANCE_PAGE_ID);
81          }
82  
83          //Compare rule with parent rule.
84          compareRulePropositions((MaintenanceDocumentForm) form, ruleEditor);
85  
86          return super.navigate(form, result, request, response);
87      }
88  
89      /**
90       * Deletes selected rule from agenda on Manage Course Requistes page
91       *
92       * @param form
93       * @param result
94       * @param request
95       * @param response
96       * @return
97       */
98      @RequestMapping(params = "methodToCall=deleteRule")
99      public ModelAndView deleteRule(@ModelAttribute("KualiForm") UifFormBase form, @SuppressWarnings("unused") BindingResult result,
100                                    @SuppressWarnings("unused") HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) {
101 
102         MaintenanceDocumentForm document = (MaintenanceDocumentForm) form;
103         RuleManagementWrapper ruleWrapper = AgendaUtilities.getRuleWrapper(document);
104         String ruleKey = AgendaUtilities.getRuleKey(document);
105 
106         AgendaEditor agenda = AgendaUtilities.getSelectedAgendaEditor(ruleWrapper, ruleKey);
107         if (agenda != null) {
108             RuleEditor ruleEditor = agenda.getRuleEditors().get(ruleKey);
109 
110             //Only add rules to delete list that are already persisted.
111             if (ruleEditor.getId() != null) {
112                 agenda.getDeletedRules().add(ruleEditor);
113             }
114 
115             RuleEditor dummyRule = new RuleEditor(ruleEditor.getKey(), true, ruleEditor.getRuleTypeInfo());
116             dummyRule.setParent(ruleEditor.getParent());
117             agenda.getRuleEditors().put(ruleEditor.getKey(), dummyRule);
118         }
119 
120         return getUIFModelAndView(document);
121     }
122 
123     /**
124      * Navigates to rule maintenance page with rule type to initialize adding of new rule.
125      *
126      * @param form
127      * @param result
128      * @param request
129      * @param response
130      * @return
131      */
132     @RequestMapping(params = "methodToCall=addRule")
133     public ModelAndView addRule(@ModelAttribute("KualiForm") UifFormBase form, @SuppressWarnings("unused") BindingResult result,
134                                 @SuppressWarnings("unused") HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) {
135 
136         //Clear the client state on new edit rule.
137         form.getClientStateForSyncing().clear();
138 
139         RuleEditor ruleEditor = AgendaUtilities.retrieveSelectedRuleEditor((MaintenanceDocumentForm) form);
140 
141         this.getViewHelper(form).refreshInitTrees(ruleEditor);
142 
143         if (!form.getActionParameters().containsKey(UifParameters.NAVIGATE_TO_PAGE_ID)) {
144             form.getActionParameters().put(UifParameters.NAVIGATE_TO_PAGE_ID, KRMSConstants.KRMS_RULE_MAINTENANCE_PAGE_ID);
145         }
146         return super.navigate(form, result, request, response);
147     }
148 
149     /**
150      * Call the super method to avoid the agenda tree being reloaded from the db.
151      *
152      * @param form
153      * @param result
154      * @param request
155      * @param response
156      * @return
157      * @throws Exception
158      */
159     @RequestMapping(params = "methodToCall=ajaxRefresh")
160     public ModelAndView ajaxRefresh(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
161                                     HttpServletRequest request, HttpServletResponse response) {
162         return getUIFModelAndView(form);
163     }
164 
165     /**
166      * Retrieves selected rule editor from data object.
167      *
168      * @param form
169      * @return the current rule editor
170      */
171     protected RuleEditor getRuleEditor(UifFormBase form) {
172         if (form instanceof MaintenanceDocumentForm) {
173             MaintenanceDocumentForm maintenanceDocumentForm = (MaintenanceDocumentForm) form;
174             Object dataObject = maintenanceDocumentForm.getDocument().getNewMaintainableObject().getDataObject();
175 
176             if (dataObject instanceof RuleEditor) {
177                 return (RuleEditor) dataObject;
178             } else if (dataObject instanceof RuleManagementWrapper) {
179                 RuleManagementWrapper wrapper = (RuleManagementWrapper) dataObject;
180                 return wrapper.getRuleEditor();
181             }
182         }
183 
184         return null;
185     }
186 
187     //
188     // Rule Editor Controller methods
189     //
190 
191     /**
192      * Method to copy rule.
193      *
194      * @param form
195      * @param result
196      * @param request
197      * @param response
198      * @return
199      * @throws Exception
200      */
201     @RequestMapping(params = "methodToCall=copyRule")
202     public ModelAndView copyRule(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
203                                  HttpServletRequest request, HttpServletResponse response) throws Exception {
204         return super.refresh(form, result, request, response);
205     }
206 
207     /**
208      * This method starts an edit on proposition.
209      *
210      * @param form
211      * @param result
212      * @param request
213      * @param response
214      * @return
215      */
216     @RequestMapping(params = "methodToCall=goToEditProposition")
217     public ModelAndView goToEditProposition(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
218                                             HttpServletRequest request, HttpServletResponse response) {
219 
220         RuleViewHelperService viewHelper = this.getViewHelper(form);
221         RuleEditor ruleEditor = getRuleEditor(form);
222 
223         PropositionTreeUtil.resetEditModeOnPropositionTree(ruleEditor.getPropositionEditor());
224         PropositionEditor proposition = PropositionTreeUtil.getProposition(ruleEditor);
225         proposition.setEditMode(true);
226 
227         if (!PropositionType.COMPOUND.getCode().equalsIgnoreCase(proposition.getPropositionTypeCode())) {
228 
229             String propositionTypeId = proposition.getTypeId();
230             if (propositionTypeId == null) {
231                 proposition.setType(null);
232             } else {
233 
234                 KrmsTypeDefinition type = KrmsRepositoryServiceLocator.getKrmsTypeRepositoryService().getTypeById(propositionTypeId);
235                 if (type != null) {
236                     proposition.setType(type.getName());
237                 }
238             }
239 
240         }
241 
242         //refresh the tree
243         viewHelper.refreshInitTrees(ruleEditor);
244 
245         return getUIFModelAndView(form);
246     }
247 
248     /**
249      * Method to initialize the adding of proposition to rule.
250      *
251      * @param form
252      * @param result
253      * @param request
254      * @param response
255      * @return
256      */
257     @RequestMapping(params = "methodToCall=addProposition")
258     public ModelAndView addProposition(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
259                                        HttpServletRequest request, HttpServletResponse response) {
260 
261         RuleEditor ruleEditor = getRuleEditor(form);
262         String selectedPropKey = ruleEditor.getSelectedKey();
263 
264         // find parent
265         Node<RuleEditorTreeNode, String> root = ruleEditor.getEditTree().getRootElement();
266         Node<RuleEditorTreeNode, String> parent = PropositionTreeUtil.findParentPropositionNode(root, selectedPropKey);
267 
268         //PropositionTreeUtil.resetEditModeOnPropositionTree(ruleEditor);
269         RuleViewHelperService viewHelper = this.getViewHelper(form);
270 
271         //Special case when only one proposition in tree or no proposition selected
272         if (selectedPropKey.isEmpty() && parent == null && root.getChildren().size() > 0) {
273             //Special case when now proposition selected and more than one proposition in tree
274             if (root.getChildren().get(root.getChildren().size() - 1).getNodeType().contains("compoundNode")) {
275                 parent = root.getChildren().get(root.getChildren().size() - 1);
276                 selectedPropKey = parent.getChildren().get(parent.getChildren().size() - 1).getData().getProposition().getKey();
277             } //Special case when one proposition in tree and no proposition selected
278             else {
279                 parent = root;
280                 selectedPropKey = root.getChildren().get(root.getChildren().size() - 1).getData().getProposition().getKey();
281             }
282         } //If root compound proposition selected
283         else if (parent != null) {
284             if (parent.getNodeType().equals("treeRoot") && !parent.getChildren().get(parent.getChildren().size() - 1).getNodeType().contains("simple")) {
285                 parent = root.getChildren().get(root.getChildren().size() - 1);
286                 selectedPropKey = parent.getChildren().get(parent.getChildren().size() - 1).getData().getProposition().getKey();
287             }
288         }
289 
290         // add new child at appropriate spot
291         if (parent != null) {
292             List<Node<RuleEditorTreeNode, String>> children = parent.getChildren();
293             for (int index = 0; index < children.size(); index++) {
294                 Node<RuleEditorTreeNode, String> child = children.get(index);
295 
296                 // if our selected node is a simple proposition, add a new one after
297                 if (propKeyMatches(child, selectedPropKey)) {
298                     // handle special case of adding to a lone simple proposition.
299                     // in this case, we need to change the root level proposition to a compound proposition
300                     // move the existing simple proposition as the first compound component,
301                     // then add a new blank simple prop as the second compound component.
302                     PropositionEditor blank = null;
303                     if (parent.equals(root) && (isSimpleNode(child.getNodeType()))) {
304 
305                         // create a new compound proposition
306                         blank = viewHelper.createCompoundPropositionBoStub(child.getData().getProposition(), true);
307                         // don't set compound.setEditMode(true) as the Simple Prop in the compound prop is the only prop in edit mode
308                         ruleEditor.setProposition(blank);
309                     }
310                     // handle regular case of adding a simple prop to an existing compound prop
311                     else if (!parent.equals(root)) {
312 
313                         // build new Blank Proposition
314                         blank = viewHelper.createSimplePropositionBoStub(child.getData().getProposition());
315                         //add it to the parent
316                         PropositionEditor parentProp = parent.getData().getProposition();
317                         parentProp.getCompoundEditors().add(((index / 2) + 1), blank);
318                     } else {
319                         return getUIFModelAndView(form);
320                     }
321                     this.getViewHelper(form).refreshInitTrees(ruleEditor);
322                     if (blank != null) {
323                         ruleEditor.setSelectedKey(blank.getKey());
324                     } else {
325                         ruleEditor.setSelectedKey(null);
326                     }
327                     break;
328                 }
329             }
330         } else {
331             // special case, if root has no children, add a new simple proposition
332             if (root.getChildren().isEmpty()) {
333                 PropositionEditor blank = viewHelper.createSimplePropositionBoStub(null);
334                 blank.setRuleId(ruleEditor.getId());
335                 ruleEditor.setPropId(blank.getId());
336                 ruleEditor.setProposition(blank);
337             }
338             this.getViewHelper(form).refreshInitTrees(ruleEditor);
339         }
340         return getUIFModelAndView(form);
341     }
342 
343     /**
344      * Returns <code>true</code> if proposition key matches tree node key
345      *
346      * @param node
347      * @param propKey
348      * @return if proposition key matches tree node key; <code>false</code> otherwise
349      */
350     private boolean propKeyMatches(Node<RuleEditorTreeNode, String> node, String propKey) {
351         if (propKey != null && node != null && node.getData() != null && propKey.equalsIgnoreCase(node.getData().getProposition().getKey())) {
352             return true;
353         }
354         return false;
355     }
356 
357     /**
358      * This method return the index of the position of the child that matches the id
359      *
360      * @param parent
361      * @param propKey
362      * @return index if found, -1 if not found
363      */
364     private int findChildIndex(Node<RuleEditorTreeNode, String> parent, String propKey) {
365         int index;
366         List<Node<RuleEditorTreeNode, String>> children = parent.getChildren();
367         for (index = 0; index < children.size(); index++) {
368             Node<RuleEditorTreeNode, String> child = children.get(index);
369             // if our selected node is a simple proposition, add a new one after
370             if (propKeyMatches(child, propKey)) {
371                 return index;
372             }
373         }
374         return -1;
375     }
376 
377     /**
378      * Moves proposition up in tree structure.
379      *
380      * @param form
381      * @param result
382      * @param request
383      * @param response
384      * @return
385      */
386     @RequestMapping(params = "methodToCall=movePropositionUp")
387     public ModelAndView movePropositionUp(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
388                                           HttpServletRequest request, HttpServletResponse response) {
389         moveSelectedProposition(form, true);
390 
391         return getUIFModelAndView(form);
392     }
393 
394     /**
395      * Moves proposition down in tree structure.
396      *
397      * @param form
398      * @param result
399      * @param request
400      * @param response
401      * @return
402      */
403     @RequestMapping(params = "methodToCall=movePropositionDown")
404     public ModelAndView movePropositionDown(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
405                                             HttpServletRequest request, HttpServletResponse response) {
406         moveSelectedProposition(form, false);
407 
408         return getUIFModelAndView(form);
409     }
410 
411     /**
412      * Moves proposition up or down.
413      * <p/>
414      * Rough algorithm for moving a node up.
415      * <p/>
416      * find the following:
417      * node := the selected node
418      * parent := the selected node's parent, its containing node (via when true or when false relationship)
419      * parentsOlderCousin := the parent's level-order predecessor (sibling or cousin)
420      *
421      * @param form
422      * @param up   whether the desired move is in an up direction
423      * @throws Exception
424      */
425     private void moveSelectedProposition(UifFormBase form, boolean up) {
426 
427         RuleEditor ruleEditor = getRuleEditor(form);
428         String selectedPropKey = ruleEditor.getSelectedKey();
429 
430         // find parent
431         Node<RuleEditorTreeNode, String> parent = PropositionTreeUtil.findParentPropositionNode(ruleEditor.getEditTree().getRootElement(), selectedPropKey);
432 
433         // add new child at appropriate spot
434         if (parent != null) {
435             List<Node<RuleEditorTreeNode, String>> children = parent.getChildren();
436             for (int index = 0; index < children.size(); index++) {
437                 Node<RuleEditorTreeNode, String> child = children.get(index);
438                 // if our selected node is a simple proposition, add a new one after
439                 if (propKeyMatches(child, selectedPropKey) &&
440                         (isSimpleNode(child.getNodeType()) ||
441                                 (RuleEditorTreeNode.COMPOUND_NODE_TYPE.equalsIgnoreCase(child.getNodeType())) ||
442                                 (child.getNodeType().contains(RuleEditorTreeNode.FIRST_IN_GROUP)) ||
443                                 (child.getNodeType().contains(RuleEditorTreeNode.LAST_IN_GROUP)))) {
444 
445                     //remove it from its current spot
446                     PropositionEditor parentProp = parent.getData().getProposition();
447                     PropositionEditor workingProp = null;
448                     if (index != 0 && up) {
449                         workingProp = parentProp.getCompoundEditors().remove(index / 2);
450                     } else if (!up && index != (children.size() - 1)) {
451                         workingProp = parentProp.getCompoundEditors().remove(index / 2);
452                     }
453                     if ((index > 0) && up) {
454                         parentProp.getCompoundEditors().add((index / 2) - 1, workingProp);
455                     } else if ((index < (children.size() - 1) && !up)) {
456                         parentProp.getCompoundEditors().add((index / 2) + 1, workingProp);
457                     }
458                     // redisplay the tree (editMode = true)
459                     this.getViewHelper(form).refreshInitTrees(ruleEditor);
460                     break;
461                 }
462             }
463         }
464         //Compare rule with parent rule.
465         compareRulePropositions((MaintenanceDocumentForm) form, ruleEditor);
466 
467     }
468 
469     /**
470      * Returns <code>true</code> if node is of type simple
471      *
472      * @param nodeType
473      * @return if node is of type simple; <code>false</code> otherwise
474      */
475     public boolean isSimpleNode(String nodeType) {
476         if (nodeType.contains(SimplePropositionNode.NODE_TYPE) ||
477                 SimplePropositionEditNode.NODE_TYPE.equalsIgnoreCase(nodeType)) {
478             return true;
479         }
480         return false;
481     }
482 
483     /**
484      * Moves proposition left in tree structure.
485      * <p/>
486      * Rough algorithm for moving a node up.
487      * <p/>
488      * find the following:
489      * node := the selected node
490      * parent := the selected node's parent, its containing node (via when true or when false relationship)
491      * parentsOlderCousin := the parent's level-order predecessor (sibling or cousin)
492      *
493      * @param form
494      * @param result
495      * @param request
496      * @param response
497      * @return
498      */
499     @RequestMapping(params = "methodToCall=movePropositionLeft")
500     public ModelAndView movePropositionLeft(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
501                                             HttpServletRequest request, HttpServletResponse response) {
502 
503         RuleEditor ruleEditor = getRuleEditor(form);
504         String selectedpropKey = ruleEditor.getSelectedKey();
505 
506         // find agendaEditor.getAgendaItemLine().getRule().getPropositionTree().getRootElement()parent
507         Node<RuleEditorTreeNode, String> root = ruleEditor.getEditTree().getRootElement();
508         Node<RuleEditorTreeNode, String> parent = PropositionTreeUtil.findParentPropositionNode(root, selectedpropKey);
509         if ((parent != null) && (!parent.getNodeType().contains(RuleEditorTreeNode.ROOT_TYPE))) {
510             Node<RuleEditorTreeNode, String> granny = PropositionTreeUtil.findParentPropositionNode(root, parent.getData().getProposition().getKey());
511             if (!granny.equals(root)) {
512                 int oldIndex = findChildIndex(parent, selectedpropKey);
513                 int newIndex = findChildIndex(granny, parent.getData().getProposition().getKey());
514                 if (oldIndex >= 0 && newIndex >= 0) {
515                     PropositionEditor prop = parent.getData().getProposition().getCompoundEditors().remove(oldIndex / 2);
516                     if ((parent.getChildren().size() == 1) || (parent.getChildren().size() == 3)) {
517                         PropositionTreeUtil.removeCompoundProp(ruleEditor.getPropositionEditor());
518                     }
519                     if (granny.getData().getProposition().getCompoundEditors().isEmpty()) {
520                         granny.getData().getProposition().getCompoundEditors().add(newIndex, prop);
521                     } else {
522                         granny.getData().getProposition().getCompoundEditors().add((newIndex / 2) + 1, prop);
523                     }
524                     this.getViewHelper(form).refreshInitTrees(ruleEditor);
525                 }
526             }
527 
528         }
529         //Compare rule with parent rule.
530         compareRulePropositions((MaintenanceDocumentForm) form, ruleEditor);
531         return getUIFModelAndView(form);
532     }
533 
534     /**
535      * Move proposition right in tree structure.
536      * <p/>
537      * Rough algorithm for moving a node Right
538      * if the selected node is above a compound proposition, move it into the compound proposition as the first child
539      * if the node is above a simple proposition, do nothing.
540      * find the following:
541      * node := the selected node
542      * parent := the selected node's parent, its containing node
543      * nextSibling := the node after the selected node
544      *
545      * @param form
546      * @param result
547      * @param request
548      * @param response
549      * @return
550      */
551     @RequestMapping(params = "methodToCall=movePropositionRight")
552     public ModelAndView movePropositionRight(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
553                                              HttpServletRequest request, HttpServletResponse response) {
554 
555         RuleEditor ruleEditor = getRuleEditor(form);
556         String selectedpropKey = ruleEditor.getSelectedKey();
557 
558         // find parent
559         Node<RuleEditorTreeNode, String> parent = PropositionTreeUtil.findParentPropositionNode(
560                 ruleEditor.getEditTree().getRootElement(), selectedpropKey);
561         if (parent != null) {
562             int index = findChildIndex(parent, selectedpropKey);
563             // if we are the last child, do nothing, otherwise
564             if (index >= 0 && index + 1 < parent.getChildren().size()) {
565                 Node<RuleEditorTreeNode, String> nextSibling = parent.getChildren().get(index + 2);
566                 // if selected node above a compound node, move it into it as first child
567                 if (nextSibling.getNodeType().contains(RuleEditorTreeNode.COMPOUND_NODE_TYPE)) {
568                     // remove selected node from it's current spot
569                     PropositionEditor prop = parent.getData().getProposition().getCompoundEditors().remove(index / 2);
570                     // add it to it's siblings children
571                     nextSibling.getData().getProposition().getCompoundEditors().add(0, prop);
572                 }
573                 //Remove single parents and refresh the tree.
574                 PropositionTreeUtil.removeCompoundProp(parent.getData().getProposition());
575                 this.getViewHelper(form).refreshInitTrees(ruleEditor);
576             }
577         }
578         //Compare rule with parent rule.
579         compareRulePropositions((MaintenanceDocumentForm) form, ruleEditor);
580         return getUIFModelAndView(form);
581     }
582 
583     /**
584      * Introduces a new compound proposition between the selected proposition and its parent.
585      * Additionally, it puts a new blank simple proposition underneath the compound proposition
586      * as a sibling to the selected proposition.
587      *
588      * @param form
589      * @param result
590      * @param request
591      * @param response
592      * @return
593      * @throws Exception
594      */
595     @RequestMapping(params = "methodToCall=togglePropositionSimpleCompound")
596     public ModelAndView togglePropositionSimpleCompound(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
597                                                         HttpServletRequest request, HttpServletResponse response) {
598 
599         RuleEditor ruleEditor = getRuleEditor(form);
600         String selectedPropKey = ruleEditor.getSelectedKey();
601 
602         PropositionTreeUtil.resetEditModeOnPropositionTree(ruleEditor.getPropositionEditor());
603         RuleViewHelperService viewHelper = this.getViewHelper(form);
604 
605         if (!StringUtils.isBlank(selectedPropKey)) {
606             // find parent
607             Node<RuleEditorTreeNode, String> parent = PropositionTreeUtil.findParentPropositionNode(
608                     ruleEditor.getEditTree().getRootElement(), selectedPropKey);
609             if (parent != null) {
610 
611                 int index = findChildIndex(parent, selectedPropKey);
612                 PropositionEditor propBo = parent.getChildren().get(index).getData().getProposition();
613 
614                 // create a new compound proposition
615                 PropositionEditor compound = viewHelper.createCompoundPropositionBoStub(propBo, true);
616 
617                 if (parent.getData() == null) { // SPECIAL CASE: this is the only proposition in the tree
618                     ruleEditor.setProposition(compound);
619                 } else {
620                     PropositionEditor parentBo = parent.getData().getProposition();
621                     List<PropositionEditor> siblings = parentBo.getCompoundEditors();
622 
623                     int propIndex = -1;
624                     for (int i = 0; i < siblings.size(); i++) {
625                         if (propBo.getKey().equals(siblings.get(i).getKey())) {
626                             propIndex = i;
627                             break;
628                         }
629                     }
630 
631                     parentBo.getCompoundEditors().set(propIndex, compound);
632                     compound.getCompoundEditors().get(1).setEditMode(true);
633                 }
634 
635                 viewHelper.refreshInitTrees(ruleEditor);
636                 ruleEditor.setSelectedKey(compound.getCompoundEditors().get(1).getKey());
637 
638             }
639         }
640 
641         return getUIFModelAndView(form);
642     }
643 
644     /**
645      * Paste proposition in selected position in tree structure.
646      *
647      * @param form
648      * @param result
649      * @param request
650      * @param response
651      * @return
652      * @throws Exception
653      */
654     @RequestMapping(params = "methodToCall=pasteProposition")
655     public ModelAndView pasteProposition(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
656                                          HttpServletRequest request, HttpServletResponse response) {
657 
658         boolean cutAction = true;
659         RuleEditor ruleEditor = getRuleEditor(form);
660         RuleViewHelperService viewHelper = this.getViewHelper(form);
661 
662         // get selected id
663         String selectedPropKey = ruleEditor.getSelectedKey();
664         if (StringUtils.isBlank(selectedPropKey)) {
665             return getUIFModelAndView(form);
666         }
667 
668         // get the id to move
669         String movePropKey = ruleEditor.getCutKey();
670         if (StringUtils.isBlank(movePropKey)) {
671             movePropKey = ruleEditor.getCopyKey();
672             cutAction = false;
673         }
674 
675         // check if selected and move is not the same
676         if (StringUtils.isNotBlank(movePropKey)) {
677 
678             PropositionEditor newParent = null;
679             PropositionEditor workingProp = null;
680             PropositionEditor root = ruleEditor.getPropositionEditor();
681 
682             // Special case when the user copy the the only proposition in tree.
683             if (movePropKey.equals(root.getKey())) {
684                 newParent = viewHelper.createCompoundPropositionBoStub(root, false);
685                 workingProp = viewHelper.copyProposition(root);
686             } else {
687                 Node<RuleEditorTreeNode, String> rootNode = ruleEditor.getEditTree().getRootElement();
688                 if (selectedPropKey.equals(root.getKey())) {
689                     newParent = root;
690                 } else {
691                     newParent = PropositionTreeUtil.findParentPropositionNode(rootNode, selectedPropKey).getData().getProposition();
692                 }
693                 PropositionEditor oldParent = PropositionTreeUtil.findParentPropositionNode(rootNode, movePropKey).getData().getProposition();
694 
695                 // cut or copy from old
696                 if (oldParent != null) {
697                     List<PropositionEditor> children = oldParent.getCompoundEditors();
698                     for (int index = 0; index < children.size(); index++) {
699                         if (movePropKey.equalsIgnoreCase(children.get(index).getKey())) {
700                             if (cutAction) {
701                                 workingProp = oldParent.getCompoundEditors().remove(index);
702                             } else {
703                                 workingProp = viewHelper.copyProposition(oldParent.getCompoundEditors().get(index));
704                             }
705                             break;
706                         }
707                     }
708                 }
709             }
710 
711             // add to new
712             addProposition(selectedPropKey, newParent, workingProp);
713             if (movePropKey.equals(root.getKey())) {
714                 ruleEditor.setProposition(newParent);
715             }
716 
717             //Refresh the tree.
718             PropositionTreeUtil.removeCompoundProp(ruleEditor);
719             ruleEditor.setSelectedKey(StringUtils.EMPTY);
720             viewHelper.refreshInitTrees(ruleEditor);
721         }
722 
723         //Compare rule with parent rule.
724         compareRulePropositions((MaintenanceDocumentForm) form, ruleEditor);
725 
726         // call the super method to avoid the agenda tree being reloaded from the db
727         return getUIFModelAndView(form);
728     }
729 
730     /**
731      * Adds proposition at selected position.
732      *
733      * @param selectedpropKey
734      * @param newParent
735      * @param workingProp
736      */
737     private void addProposition(String selectedpropKey, PropositionEditor newParent, PropositionEditor workingProp) {
738         // add to new
739         if (newParent != null && workingProp != null) {
740             //Selected is parent, add to list.
741             if(selectedpropKey.equalsIgnoreCase(newParent.getKey())){
742                 newParent.getCompoundEditors().add(workingProp);
743                 return;
744             }
745 
746             //Add after selected prop.
747             List<PropositionEditor> children = newParent.getCompoundEditors();
748             for (int index = 0; index < children.size(); index++) {
749                 if (selectedpropKey.equalsIgnoreCase(children.get(index).getKey())) {
750                     children.add(index + 1, workingProp);
751                     return;
752                 }
753             }
754         }
755     }
756 
757     /**
758      * Removes proposition.
759      *
760      * @param form
761      * @param result
762      * @param request
763      * @param response
764      * @return
765      */
766     @RequestMapping(params = "methodToCall=deleteProposition")
767     public ModelAndView deleteProposition(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
768                                           HttpServletRequest request, HttpServletResponse response) {
769         RuleEditor ruleEditor = getRuleEditor(form);
770         String selectedpropKey = ruleEditor.getSelectedKey();
771         Node<RuleEditorTreeNode, String> root = ruleEditor.getEditTree().getRootElement();
772 
773         Node<RuleEditorTreeNode, String> parentNode = PropositionTreeUtil.findParentPropositionNode(root, selectedpropKey);
774 
775         // what if it is the root?
776         if (parentNode != null && parentNode.getData() != null) { // it is not the root as there is a parent w/ a prop
777             PropositionEditor parent = parentNode.getData().getProposition();
778             if (parent != null) {
779                 List<PropositionEditor> children = parent.getCompoundEditors();
780                 for (int index = 0; index < children.size(); index++) {
781                     if (selectedpropKey.equalsIgnoreCase(children.get(index).getKey())) {
782                         parent.getCompoundComponents().remove(index);
783                         break;
784                     }
785                 }
786             }
787             PropositionTreeUtil.removeCompoundProp(ruleEditor);
788             ruleEditor.setSelectedKey(StringUtils.EMPTY);
789         } else { // no parent, it is the root
790             ruleEditor.reset();
791         }
792 
793         //Compare rule with parent rule.
794         compareRulePropositions((MaintenanceDocumentForm) form, ruleEditor);
795 
796         this.getViewHelper(form).refreshInitTrees(ruleEditor);
797         return getUIFModelAndView(form);
798     }
799 
800     /**
801      * Updates compound operator in tree structure.
802      *
803      * @param form
804      * @param result
805      * @param request
806      * @param response
807      * @return
808      */
809     @RequestMapping(params = "methodToCall=updateCompoundOperator")
810     public ModelAndView updateCompoundOperator(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
811                                                HttpServletRequest request, HttpServletResponse response) {
812 
813         RuleEditor ruleEditor = getRuleEditor(form);
814         String selectedpropKey = ruleEditor.getSelectedKey();
815         Node<RuleEditorTreeNode, String> parentNode = PropositionTreeUtil.findParentPropositionNode(ruleEditor.getEditTree().getRootElement(), selectedpropKey);
816         PropositionEditor parent = parentNode.getData().getProposition();
817 
818         PropositionEditor proposition = PropositionTreeUtil.findProposition(parentNode, selectedpropKey);
819 
820         RuleViewHelperService viewHelper = this.getViewHelper(form);
821         viewHelper.setTypeForCompoundOpCode(parent, proposition.getCompoundOpCode());
822         viewHelper.resetDescription(parent);
823         viewHelper.refreshInitTrees(ruleEditor);
824 
825         //Compare rule with parent rule.
826         compareRulePropositions((MaintenanceDocumentForm) form, ruleEditor);
827 
828         return getUIFModelAndView(form);
829     }
830 
831     /**
832      * Updates rule with new or changed propositions.
833      *
834      * @param form
835      * @param result
836      * @param request
837      * @param response
838      * @return
839      * @throws Exception
840      */
841     @RequestMapping(params = "methodToCall=updateProposition")
842     public ModelAndView updateProposition(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
843                                           HttpServletRequest request, HttpServletResponse response) {
844 
845         //Reset the description on current selected proposition
846         RuleEditor ruleEditor = getRuleEditor(form);
847         PropositionEditor proposition = PropositionTreeUtil.getProposition(ruleEditor);
848         if (proposition != null) {
849 
850             //Validate the proposition and return if has errors.
851             this.getViewHelper(form).validateProposition(proposition);
852             if (!GlobalVariables.getMessageMap().getErrorMessages().isEmpty()) {
853                 return getUIFModelAndView(form);
854             }
855 
856             if (!GlobalVariables.getMessageMap().getWarningMessages().isEmpty()) {
857                 if (!hasDialogBeenAnswered(KRMSConstants.KSKRMS_DIALOG_YESNO_WARNING, form)) {
858                     return showDialog(KRMSConstants.KSKRMS_DIALOG_YESNO_WARNING, form, request, response);
859                 }
860 
861                 String dialogResponse = getStringDialogResponse(KRMSConstants.KSKRMS_DIALOG_YESNO_WARNING, form, request, response);
862                 if ("N".equals(dialogResponse)) {
863                     form.getDialogManager().resetDialogStatus(KRMSConstants.KSKRMS_DIALOG_YESNO_WARNING);
864                     return getUIFModelAndView(form);
865                 }
866             }
867 
868             //Reset the description and natural language for the proposition.
869             this.getViewHelper(form).resetDescription(proposition);
870             if (!GlobalVariables.getMessageMap().getErrorMessages().isEmpty()) {
871                 return getUIFModelAndView(form);
872             }
873 
874             //Check if the proposition that was edited is the root proposition and replace.
875             if (ruleEditor.getPropositionEditor().getKey().equals(ruleEditor.getSelectedKey())) {
876                 ruleEditor.setProposition(proposition);
877             } else {
878                 //Replace old proposition if not the root proposition.
879                 this.setUpdatedProposition(ruleEditor.getPropositionEditor(), proposition);
880             }
881 
882         }
883 
884         if (ruleEditor.getProposition() != null) {
885             PropositionTreeUtil.resetNewProp(ruleEditor.getPropositionEditor());
886         }
887 
888         // clear dialog history so user can press the button again
889         form.getDialogManager().resetDialogStatus(KRMSConstants.KSKRMS_DIALOG_YESNO_WARNING);
890 
891         //Compare rule with parent rule.
892         compareRulePropositions((MaintenanceDocumentForm) form, ruleEditor);
893 
894         //Remove the edit mode
895         PropositionTreeUtil.resetEditModeOnPropositionTree(ruleEditor.getPropositionEditor());
896         this.getViewHelper(form).refreshInitTrees(ruleEditor);
897 
898         return getUIFModelAndView(form);
899     }
900 
901     /**
902      * Replace old proposition with the updated proposition once the user clicked "Update Preview". We keep the
903      * old proposition for when the user want to cancel the editing of this proposition.
904      * <p/>
905      * Recursively walk through the proposition tree and search for the proposition with the same key, if found
906      * replace it at the same index.
907      *
908      * @param proposition
909      * @param updatedProposition
910      */
911     private void setUpdatedProposition(PropositionEditor proposition, PropositionEditor updatedProposition) {
912 
913         if (proposition.getCompoundEditors() != null) {
914             for (int i = 0; i < proposition.getCompoundEditors().size(); i++) {
915                 PropositionEditor childProp = proposition.getCompoundEditors().get(i);
916                 if (childProp.getKey().equals(updatedProposition.getKey())) {
917                     proposition.getCompoundEditors().set(i, updatedProposition);
918                 } else {
919                     setUpdatedProposition(childProp, updatedProposition);
920                 }
921             }
922         }
923     }
924 
925     protected void compareRulePropositions(MaintenanceDocumentForm form, RuleEditor ruleEditor) {
926 
927         RuleManagementWrapper ruleWrapper = (RuleManagementWrapper) form.getDocument().getNewMaintainableObject().getDataObject();
928 
929         //Compare rule to parent and display info message
930         if (ruleEditor.getProposition() != null) {
931             if (!this.getViewHelper(form).compareRules(ruleWrapper.getRuleEditor())) {
932                 GlobalVariables.getMessageMap().putInfoForSectionId(KRMSConstants.KRMS_RULE_TREE_GROUP_ID, "info.krms.tree.rule.changed");
933             } else if (GlobalVariables.getMessageMap().containsMessageKey(KRMSConstants.KRMS_RULE_TREE_GROUP_ID)) {
934                 GlobalVariables.getMessageMap().removeAllInfoMessagesForProperty(KRMSConstants.KRMS_RULE_TREE_GROUP_ID);
935             }
936         }
937     }
938 
939     /**
940      * Updates rule and redirects to agenda maintenance page.
941      *
942      * @param form
943      * @param result
944      * @param request
945      * @param response
946      * @return
947      * @throws Exception
948      */
949     @RequestMapping(params = "methodToCall=updateRule")
950     public ModelAndView updateRule(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
951                                    HttpServletRequest request, HttpServletResponse response) {
952 
953         RuleEditor ruleEditor = getRuleEditor(form);
954 
955         //Return with error message if user is currently editing a proposition.
956         PropositionEditor proposition = PropositionTreeUtil.getProposition(ruleEditor);
957         if ((proposition!=null) && (proposition.isEditMode())) {
958             GlobalVariables.getMessageMap().putErrorForSectionId(KRMSConstants.KRMS_PROPOSITION_DETAILSECTION_ID, KRMSConstants.KRMS_MSG_ERROR_RULE_PREVIEW);
959             return getUIFModelAndView(form);
960         }
961 
962         if (!(ruleEditor.getProposition() == null && ruleEditor.getPropId() == null)) {
963             PropositionTreeUtil.resetEditModeOnPropositionTree(ruleEditor.getPropositionEditor());
964             ruleEditor.setDummy(false);
965             PropositionTreeUtil.resetNewProp(ruleEditor.getPropositionEditor());
966         }
967 
968         if(ruleEditor.getPropositionEditor()!=null){
969             // handle saving new parameterized terms
970             this.getViewHelper(form).finPropositionEditor(ruleEditor.getPropositionEditor());
971         }
972 
973         this.getViewHelper(form).refreshViewTree(ruleEditor);
974 
975         //Replace edited rule with existing rule.
976         RuleManagementWrapper ruleWrapper = AgendaUtilities.getRuleWrapper((MaintenanceDocumentForm) form);
977         AgendaEditor agendaEditor = AgendaUtilities.getSelectedAgendaEditor(ruleWrapper, ruleEditor.getKey());
978         agendaEditor.getRuleEditors().put(ruleEditor.getKey(), ruleEditor);
979 
980         if (!form.getActionParameters().containsKey(UifParameters.NAVIGATE_TO_PAGE_ID)) {
981             form.getActionParameters().put(UifParameters.NAVIGATE_TO_PAGE_ID, KRMSConstants.KRMS_AGENDA_MAINTENANCE_PAGE_ID);
982         }
983         return super.navigate(form, result, request, response);
984     }
985 
986     /**
987      * Updates view with changed logic expressions.
988      * Also does validation and displays necessary messages on view.
989      *
990      * @param form
991      * @param result
992      * @param request
993      * @param response
994      * @return
995      * @throws Exception
996      */
997     @RequestMapping(params = "methodToCall=updatePreview")
998     public ModelAndView updatePreview(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
999                                       HttpServletRequest request, HttpServletResponse response) {
1000         RuleEditor ruleEditor = getRuleEditor(form);
1001         parseRuleExpression(ruleEditor, this.getViewHelper(form));
1002 
1003         //Clear new collection lines to remove new collection add line only for edit tree
1004         if (form.getNewCollectionLines().size() != 1) {
1005             List<String> keys = new ArrayList<String>(form.getNewCollectionLines().keySet());
1006             for (String key : keys) {
1007                 if (key.contains(PropositionTreeUtil.EDIT_TREE_NEW_COLLECTION_LINE)) {
1008                     form.getNewCollectionLines().remove(key);
1009                 }
1010             }
1011         }
1012 
1013         this.getViewHelper(form).refreshInitTrees(ruleEditor);
1014         return getUIFModelAndView(form);
1015     }
1016 
1017     /**
1018      * Validation for logic expression.
1019      *
1020      * @param ruleEditor
1021      */
1022     private void parseRuleExpression(RuleEditor ruleEditor, RuleViewHelperService viewHelper) {
1023         RuleLogicExpressionParser ruleLogicExpressionParser = new RuleLogicExpressionParser();
1024         ruleLogicExpressionParser.setExpression(ruleEditor.getLogicArea());
1025 
1026         if(ruleEditor.getPropositionEditor()==null){
1027             GlobalVariables.getMessageMap().putInfo("document.newMaintainableObject.dataObject.logicArea", KRMSConstants.KSKRMS_MSG_INFO_LOGIC_NO_STATEMENTS);
1028             return;
1029         }
1030 
1031         //validate the expression
1032         List<String> errorMessages = new ArrayList<String>();
1033         List<String> keyList = getPropositionKeys(new ArrayList<String>(), ruleEditor.getPropositionEditor());
1034         boolean validExpression = ruleLogicExpressionParser.validateExpression(errorMessages, keyList);
1035 
1036         //show errors and don't change anything else
1037         if (!validExpression) {
1038             for (int i = 0; i < errorMessages.size(); i++) {
1039                 GlobalVariables.getMessageMap().putError("document.newMaintainableObject.dataObject.logicArea", errorMessages.get(i));
1040             }
1041             // reload page1
1042             return;
1043         }
1044 
1045         ruleEditor.setProposition(ruleLogicExpressionParser.parseExpressionIntoRule(ruleEditor, viewHelper));
1046     }
1047 
1048     /**
1049      * Returns list of proposition keys.
1050      *
1051      * @param propositionKeys
1052      * @param propositionEditor
1053      * @return
1054      */
1055     private List<String> getPropositionKeys(List<String> propositionKeys, PropositionEditor propositionEditor) {
1056         propositionKeys.add(propositionEditor.getKey());
1057         if (propositionEditor.getCompoundComponents() != null) {
1058             for (PropositionEditor child : propositionEditor.getCompoundEditors()) {
1059                 this.getPropositionKeys(propositionKeys, child);
1060             }
1061         }
1062         return propositionKeys;
1063     }
1064 
1065     /**
1066      * Reverts rule to previous state and refreshes view.
1067      *
1068      * @param form
1069      * @param result
1070      * @param request
1071      * @param response
1072      * @return
1073      */
1074     @RequestMapping(params = "methodToCall=cancelEditProposition")
1075     public ModelAndView cancelEditProposition(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
1076                                               HttpServletRequest request, HttpServletResponse response) {
1077 
1078         RuleEditor ruleEditor = getRuleEditor(form);
1079         PropositionEditor root = ruleEditor.getPropositionEditor();
1080 
1081         //If first root and not yet updated, clear rule root
1082         if (root.isNewProp() && root.isEditMode()) {
1083             ruleEditor.reset();
1084         } else {
1085             PropositionTreeUtil.cancelNewProp(root);
1086             PropositionTreeUtil.removeCompoundProp(ruleEditor);
1087 
1088             ruleEditor.setSelectedKey(StringUtils.EMPTY);
1089             PropositionTreeUtil.resetEditModeOnPropositionTree(ruleEditor.getPropositionEditor());
1090         }
1091 
1092         //Clear new collection lines to remove new collection add line only for edit tree
1093         if (form.getNewCollectionLines().size() != 1) {
1094             List<String> keys = new ArrayList<String>(form.getNewCollectionLines().keySet());
1095             for (String key : keys) {
1096                 if (key.contains(PropositionTreeUtil.EDIT_TREE_NEW_COLLECTION_LINE)) {
1097                     form.getNewCollectionLines().remove(key);
1098                 }
1099             }
1100         }
1101 
1102         this.getViewHelper(form).refreshInitTrees(ruleEditor);
1103 
1104         //Compare rule with parent rule.
1105         compareRulePropositions((MaintenanceDocumentForm) form, ruleEditor);
1106 
1107         return getUIFModelAndView(form);
1108     }
1109 
1110     /**
1111      * Reverts rule to previous state and navigates to agenda maintenance page.
1112      *
1113      * @param form
1114      * @param result
1115      * @param request
1116      * @param response
1117      * @return
1118      */
1119     @RequestMapping(params = "methodToCall=cancelEditRule")
1120     public ModelAndView cancelEditRule(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
1121                                        HttpServletRequest request, HttpServletResponse response) {
1122 
1123         RuleEditor ruleEditor = getRuleEditor(form);
1124         PropositionEditor proposition = ruleEditor.getPropositionEditor();
1125 
1126         //Reset the editing tree.
1127         if (proposition != null) {
1128             PropositionTreeUtil.cancelNewProp(proposition);
1129         }
1130         PropositionTreeUtil.resetEditModeOnPropositionTree(ruleEditor.getPropositionEditor());
1131 
1132         if (!form.getActionParameters().containsKey(UifParameters.NAVIGATE_TO_PAGE_ID)) {
1133             form.getActionParameters().put(UifParameters.NAVIGATE_TO_PAGE_ID, KRMSConstants.KRMS_AGENDA_MAINTENANCE_PAGE_ID);
1134         }
1135         return super.navigate(form, result, request, response);
1136     }
1137 
1138     /**
1139      * Updates proposition type and reloads view.
1140      *
1141      * @param form
1142      * @param result
1143      * @param request
1144      * @param response
1145      * @return
1146      */
1147     @RequestMapping(params = "methodToCall=updatePropositionType")
1148     public ModelAndView updatePropositionType(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
1149                                               HttpServletRequest request, HttpServletResponse response) {
1150 
1151         PropositionEditor proposition = PropositionTreeUtil.getProposition(this.getRuleEditor(form));
1152         proposition.clear();
1153         this.getViewHelper(form).configurePropositionForType(proposition);
1154 
1155         return getUIFModelAndView(form);
1156     }
1157 
1158     /**
1159      * Test method for a controller that invokes a dialog lightbox.
1160      *
1161      * @param form     - test form
1162      * @param result   - Spring form binding result
1163      * @param request  - http request
1164      * @param response - http response
1165      * @return
1166      */
1167     @RequestMapping(params = "methodToCall=compareRules")
1168     public ModelAndView compareRules(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
1169                                      HttpServletRequest request, HttpServletResponse response) {
1170 
1171         doCompareRules(form);
1172 
1173         // redirect back to client to display lightbox
1174         return showDialog(KRMSConstants.KSKRMS_DIALOG_COMPARE, form, request, response);
1175     }
1176 
1177     protected void doCompareRules(UifFormBase form) {
1178         MaintenanceDocumentForm document = (MaintenanceDocumentForm) form;
1179         Object dataObject = document.getDocument().getNewMaintainableObject().getDataObject();
1180         if (dataObject instanceof RuleManagementWrapper) {
1181             RuleManagementWrapper ruleWrapper = (RuleManagementWrapper) dataObject;
1182             String ruleId = document.getActionParamaterValue(KRMSConstants.KRMS_PARM_RULE_KEY);
1183             RuleEditor ruleEditor = null;
1184             if ((ruleId != null) && (StringUtils.isNotBlank(ruleId))) {
1185                 //Get a specific ruleEditor based on the ruleId.
1186                 ruleEditor = AgendaUtilities.getSelectedRuleEditor(ruleWrapper, ruleId);
1187             } else {
1188                 //Get the current editing ruleEditor.
1189                 ruleEditor = ruleWrapper.getRuleEditor();
1190             }
1191 
1192             //Build the compare rule tree
1193             ruleWrapper.setCompareTree(this.getViewHelper(form).buildCompareTree(ruleEditor.getParent(), ruleEditor));
1194             ruleWrapper.setCompareLightBoxHeader(ruleEditor.getRuleTypeInfo().getDescription());
1195         }
1196     }
1197 
1198     /**
1199      * Returns form's view helper serivce.
1200      *
1201      * @param form
1202      * @return
1203      */
1204     protected RuleViewHelperService getViewHelper(UifFormBase form) {
1205         return (RuleViewHelperService) KSControllerHelper.getViewHelperService(form);
1206     }
1207 
1208     /**
1209      * Retrieves selected proposition key and initializes edit on propostion.
1210      *
1211      * @param form
1212      * @param result
1213      * @param request
1214      * @param response
1215      * @return
1216      */
1217     @RequestMapping(params = "methodToCall=getSelectedKey")
1218     public ModelAndView getSelectedKey(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
1219                                        HttpServletRequest request, HttpServletResponse response) {
1220 
1221         //Clear the current states of the tabs to open the first tab again with the edit tree.
1222         Map<String, String> states = (Map<String, String>) form.getClientStateForSyncing().get(KRMSConstants.KRMS_RULE_TABS_ID);
1223         states.put(KRMSConstants.KRMS_PARM_ACTIVE_TAB, KRMSConstants.KRMS_RULE_EDITWITHOBJECT_ID);
1224 
1225         //Set the selected rule statement key.
1226         String selectedKey = request.getParameter(KRMSConstants.KRMS_PARM_SELECTED_KEY);
1227         getRuleEditor(form).setSelectedKey(selectedKey);
1228 
1229         return this.goToEditProposition(form, result, request, response);
1230     }
1231 
1232     /**
1233      * Refreshes logic area input field when changing tabs.
1234      *
1235      * @param form
1236      * @param result
1237      * @param request
1238      * @param response
1239      * @return
1240      */
1241     @RequestMapping(params = "methodToCall=refreshLogicArea")
1242     public ModelAndView refreshLogicArea(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
1243                                        HttpServletRequest request, HttpServletResponse response) {
1244 
1245         RuleEditor rule = this.getRuleEditor(form);
1246 
1247         //Reset the logic expression.
1248         if (rule.getProposition() != null) {
1249             rule.setLogicArea(PropositionTreeUtil.configureLogicExpression(rule.getPropositionEditor()));
1250         } else {
1251             rule.setLogicArea(StringUtils.EMPTY);
1252         }
1253 
1254         return super.getUIFModelAndView(form);
1255     }
1256 
1257 }