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