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