View Javadoc

1   /**
2    * Copyright 2005-2012 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.uif.component.Component;
22  import org.kuali.rice.krad.uif.container.Group;
23  import org.kuali.rice.krad.uif.container.LinkGroup;
24  import org.kuali.rice.krad.uif.element.Action;
25  import org.kuali.rice.krad.uif.field.MessageField;
26  import org.kuali.rice.krad.uif.util.ComponentFactory;
27  import org.kuali.rice.krad.uif.util.ComponentUtils;
28  import org.kuali.rice.krad.util.GlobalVariables;
29  import org.kuali.rice.krad.web.controller.MaintenanceDocumentController;
30  import org.kuali.rice.krad.web.form.MaintenanceDocumentForm;
31  import org.kuali.rice.krad.web.form.UifFormBase;
32  import org.kuali.rice.krms.api.repository.LogicalOperator;
33  import org.kuali.rice.krms.api.repository.proposition.PropositionType;
34  import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition;
35  import org.kuali.rice.krms.dto.AgendaEditor;
36  import org.kuali.rice.krms.dto.PropositionEditor;
37  import org.kuali.rice.krms.dto.RuleEditor;
38  import org.kuali.rice.krms.dto.RuleManagementWrapper;
39  import org.kuali.rice.krms.dto.RuleTypeInfo;
40  import org.kuali.rice.krms.dto.TemplateInfo;
41  import org.kuali.rice.krms.impl.repository.KrmsRepositoryServiceLocator;
42  import org.kuali.rice.krms.impl.util.KRMSPropertyConstants;
43  import org.kuali.rice.krms.service.RuleViewHelperService;
44  import org.kuali.rice.krms.tree.RuleViewTreeBuilder;
45  import org.kuali.rice.krms.util.AgendaUtilities;
46  import org.kuali.student.enrollment.class1.krms.dto.EnrolPropositionEditor;
47  import org.kuali.student.enrollment.class1.krms.tree.node.KSSimplePropositionEditNode;
48  import org.kuali.student.enrollment.class1.krms.tree.node.KSSimplePropositionNode;
49  import org.kuali.rice.krms.tree.node.RuleEditorTreeNode;
50  import org.kuali.rice.krms.util.PropositionTreeUtil;
51  import org.kuali.rice.krms.util.RuleLogicExpressionParser;
52  import org.kuali.student.enrollment.uif.util.KSControllerHelper;
53  import org.kuali.student.krms.KRMSConstants;
54  import org.springframework.validation.BindingResult;
55  import org.springframework.web.bind.annotation.ModelAttribute;
56  import org.springframework.web.bind.annotation.RequestMapping;
57  import org.springframework.web.servlet.ModelAndView;
58  
59  import javax.servlet.http.HttpServletRequest;
60  import javax.servlet.http.HttpServletResponse;
61  import java.util.ArrayList;
62  import java.util.List;
63  
64  /**
65   * Controller for the Test UI Page
66   *
67   * @author Kuali Rice Team (rice.collab@kuali.org)
68   */
69  public class RuleEditorController extends MaintenanceDocumentController {
70  
71      /*
72      * Method used to invoke the CO inquiry view from Manage Course Offering screen while search input is Course Offering
73      * Code (04a screen)
74      */
75      @RequestMapping(params = "methodToCall=goToRuleView")
76      public ModelAndView goToRuleView(@ModelAttribute("KualiForm") UifFormBase form, @SuppressWarnings("unused") BindingResult result,
77                                       @SuppressWarnings("unused") HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) throws Exception {
78  
79          RuleEditor ruleEditor = AgendaUtilities.retrieveSelectedRuleEditor(form);
80  
81          this.getViewHelper(form).refreshInitTrees(ruleEditor);
82  
83          form.getActionParameters().put(UifParameters.NAVIGATE_TO_PAGE_ID, "KRMS-RuleMaintenance-Page");
84          return super.navigate(form, result, request, response);
85      }
86  
87      @RequestMapping(params = "methodToCall=deleteRule")
88      public ModelAndView deleteRule(@ModelAttribute("KualiForm") UifFormBase form, @SuppressWarnings("unused") BindingResult result,
89                                     @SuppressWarnings("unused") HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) throws Exception {
90          MaintenanceDocumentForm document = (MaintenanceDocumentForm) form;
91          RuleManagementWrapper ruleWrapper = (RuleManagementWrapper) document.getDocument().getNewMaintainableObject().getDataObject();
92          String ruleKey = document.getActionParamaterValue("ruleKey");
93  
94          RuleEditor ruleEditor = AgendaUtilities.getSelectedRuleEditor(ruleWrapper, ruleKey);
95  
96          List<AgendaEditor> agendas = ruleWrapper.getAgendas();
97          for (AgendaEditor agenda : agendas) {
98              if (agenda.getRuleEditors().contains(ruleEditor)) {
99                  ruleWrapper.getDeletedRuleIds().add(ruleEditor.getId());
100                 agenda.getRuleEditors().remove(ruleEditor);
101             }
102         }
103 
104         return getUIFModelAndView(document);
105     }
106 
107     @RequestMapping(params = "methodToCall=addRule")
108     public ModelAndView addRule(@ModelAttribute("KualiForm") UifFormBase form, @SuppressWarnings("unused") BindingResult result,
109                                 @SuppressWarnings("unused") HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) throws Exception {
110         RuleEditor ruleEditor = AgendaUtilities.retrieveSelectedRuleEditor(form);
111         ruleEditor.setDummy(false);
112 
113         this.getViewHelper(form).refreshInitTrees(ruleEditor);
114 
115         form.getActionParameters().put(UifParameters.NAVIGATE_TO_PAGE_ID, "KRMS-RuleMaintenance-Page");
116         return super.navigate(form, result, request, response);
117     }
118 
119     @RequestMapping(params = "methodToCall=ajaxRefresh")
120     public ModelAndView ajaxRefresh(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
121                                     HttpServletRequest request, HttpServletResponse response)
122             throws Exception {
123         // call the super method to avoid the agenda tree being reloaded from the db
124         return getUIFModelAndView(form);
125     }
126 
127     /**
128      * @param form
129      * @return the {@link org.kuali.rice.krms.impl.ui.AgendaEditor} from the form
130      */
131     protected RuleEditor getRuleEditor(UifFormBase form) {
132         if (form instanceof MaintenanceDocumentForm) {
133             MaintenanceDocumentForm maintenanceDocumentForm = (MaintenanceDocumentForm) form;
134             Object dataObject = maintenanceDocumentForm.getDocument().getNewMaintainableObject().getDataObject();
135 
136             if (dataObject instanceof RuleEditor) {
137                 return (RuleEditor) dataObject;
138             } else if (dataObject instanceof RuleManagementWrapper) {
139                 RuleManagementWrapper wrapper = (RuleManagementWrapper) dataObject;
140                 return wrapper.getRuleEditor();
141             }
142         }
143 
144         return null;
145     }
146 
147     //
148     // Rule Editor Controller methods
149     //
150     @RequestMapping(params = "methodToCall=copyRule")
151     public ModelAndView copyRule(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
152                                  HttpServletRequest request, HttpServletResponse response) throws Exception {
153 
154         //TODO: Copy rule to a different Co or AO
155 
156         return super.refresh(form, result, request, response);
157     }
158 
159     /**
160      * This method starts an edit proposition.
161      */
162     @RequestMapping(params = "methodToCall=goToEditProposition")
163     public ModelAndView goToEditProposition(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
164                                             HttpServletRequest request, HttpServletResponse response) throws Exception {
165 
166         RuleViewHelperService viewHelper = this.getViewHelper(form);
167 
168         // open the selected node for editing
169         RuleEditor ruleEditor = getRuleEditor(form);
170         String selectedpropKey = ruleEditor.getSelectedKey();
171 
172         Node<RuleEditorTreeNode, String> root = ruleEditor.getEditTree().getRootElement();
173         PropositionEditor propositionToToggleEdit = null;
174         boolean newEditMode = true;
175 
176         // find parent
177         Node<RuleEditorTreeNode, String> parent = PropositionTreeUtil.findParentPropositionNode(root, selectedpropKey);
178         if (parent != null) {
179             List<Node<RuleEditorTreeNode, String>> children = parent.getChildren();
180             for (int index = 0; index < children.size(); index++) {
181                 Node<RuleEditorTreeNode, String> child = children.get(index);
182                 if (propKeyMatches(child, selectedpropKey)) {
183                     PropositionEditor prop = child.getData().getProposition();
184                     propositionToToggleEdit = prop;
185                     newEditMode = !prop.isEditMode();
186                     break;
187                 } else {
188                     child.getData().getProposition().setEditMode(false);
189                 }
190             }
191         }
192 
193         PropositionTreeUtil.resetEditModeOnPropositionTree(ruleEditor);
194         if (propositionToToggleEdit != null) {
195             propositionToToggleEdit.setEditMode(newEditMode);
196             //refresh the tree
197             viewHelper.refreshInitTrees(ruleEditor);
198         }
199 
200         PropositionEditor proposition = PropositionTreeUtil.getProposition(ruleEditor);
201         if (!PropositionType.COMPOUND.getCode().equalsIgnoreCase(proposition.getPropositionTypeCode())) {
202 
203             String propositionTypeId = proposition.getTypeId();
204             if (propositionTypeId == null) {
205                 proposition.setType(null);
206             } else {
207 
208                 KrmsTypeDefinition type = KrmsRepositoryServiceLocator.getKrmsTypeRepositoryService().getTypeById(propositionTypeId);
209                 if (type != null) {
210                     proposition.setType(type.getName());
211                 }
212             }
213 
214         }
215 
216         return getUIFModelAndView(form);
217     }
218 
219     @RequestMapping(params = "methodToCall=addProposition")
220     public ModelAndView addProposition(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
221                                        HttpServletRequest request, HttpServletResponse response) throws Exception {
222 
223         RuleEditor ruleEditor = getRuleEditor(form);
224         String selectedPropKey = ruleEditor.getSelectedKey();
225 
226         // find parent
227         Node<RuleEditorTreeNode, String> root = ruleEditor.getEditTree().getRootElement();
228         Node<RuleEditorTreeNode, String> parent = PropositionTreeUtil.findParentPropositionNode(root, selectedPropKey);
229 
230         PropositionTreeUtil.resetEditModeOnPropositionTree(ruleEditor);
231         RuleViewHelperService viewHelper = this.getViewHelper(form);
232 
233         // add new child at appropriate spot
234         if (parent != null) {
235             List<Node<RuleEditorTreeNode, String>> children = parent.getChildren();
236             for (int index = 0; index < children.size(); index++) {
237                 Node<RuleEditorTreeNode, String> child = children.get(index);
238 
239                 // if our selected node is a simple proposition, add a new one after
240                 if (propKeyMatches(child, selectedPropKey)) {
241                     // handle special case of adding to a lone simple proposition.
242                     // in this case, we need to change the root level proposition to a compound proposition
243                     // move the existing simple proposition as the first compound component,
244                     // then add a new blank simple prop as the second compound component.
245                     PropositionEditor blank = null;
246                     if (parent.equals(root) &&
247                             (isSimpleNode(child.getNodeType()))) {
248 
249                         // create a new compound proposition
250                         blank = viewHelper.createCompoundPropositionBoStub(child.getData().getProposition(), true);
251                         blank.setDescription(KRMSConstants.PROP_COMP_DEFAULT_DESCR);
252                         // don't set compound.setEditMode(true) as the Simple Prop in the compound prop is the only prop in edit mode
253                         ruleEditor.setProposition(blank);
254                     }
255                     // handle regular case of adding a simple prop to an existing compound prop
256                     else if (!parent.equals(root)){
257 
258                         // build new Blank Proposition
259                         blank = viewHelper.createSimplePropositionBoStub(child.getData().getProposition());
260                         //add it to the parent
261                         PropositionEditor parentProp = parent.getData().getProposition();
262                         parentProp.getCompoundEditors().add(((index / 2) + 1), blank);
263                     } else {
264                         return getUIFModelAndView(form);
265                     }
266                     this.getViewHelper(form).refreshInitTrees(ruleEditor);
267                     if(blank!=null){
268                         ruleEditor.setSelectedKey(blank.getKey());
269                     }else{
270                         ruleEditor.setSelectedKey(null);
271                     }
272                     break;
273                 }
274             }
275         } else {
276             // special case, if root has no children, add a new simple proposition
277             // todo: how to add compound proposition. - just add another to the firs simple
278             if (root.getChildren().isEmpty()) {
279                 PropositionEditor blank = viewHelper.createSimplePropositionBoStub(null);
280                 blank.setRuleId(ruleEditor.getId());
281                 ruleEditor.setPropId(blank.getId());
282                 ruleEditor.setProposition(blank);
283                 this.getViewHelper(form).refreshInitTrees(ruleEditor);
284             }
285         }
286         return getUIFModelAndView(form);
287     }
288 
289     private boolean propKeyMatches(Node<RuleEditorTreeNode, String> node, String propKey) {
290         if (propKey != null && node != null && node.getData() != null && propKey.equalsIgnoreCase(node.getData().getProposition().getKey())) {
291             return true;
292         }
293         return false;
294     }
295 
296     /**
297      * This method return the index of the position of the child that matches the id
298      *
299      * @param parent
300      * @param propKey
301      * @return index if found, -1 if not found
302      */
303     private int findChildIndex(Node<RuleEditorTreeNode, String> parent, String propKey) {
304         int index;
305         List<Node<RuleEditorTreeNode, String>> children = parent.getChildren();
306         for (index = 0; index < children.size(); index++) {
307             Node<RuleEditorTreeNode, String> child = children.get(index);
308             // if our selected node is a simple proposition, add a new one after
309             if (propKeyMatches(child, propKey)) {
310                 return index;
311             }
312         }
313         return -1;
314     }
315 
316     @RequestMapping(params = "methodToCall=movePropositionUp")
317     public ModelAndView movePropositionUp(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
318                                           HttpServletRequest request, HttpServletResponse response)
319             throws Exception {
320         moveSelectedProposition(form, true);
321 
322         return getUIFModelAndView(form);
323     }
324 
325     @RequestMapping(params = "methodToCall=movePropositionDown")
326     public ModelAndView movePropositionDown(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
327                                             HttpServletRequest request, HttpServletResponse response)
328             throws Exception {
329         moveSelectedProposition(form, false);
330 
331         return getUIFModelAndView(form);
332     }
333 
334     private void moveSelectedProposition(UifFormBase form, boolean up) {
335 
336         /* Rough algorithm for moving a node up.
337          *
338          * find the following:
339          *   node := the selected node
340          *   parent := the selected node's parent, its containing node (via when true or when false relationship)
341          *   parentsOlderCousin := the parent's level-order predecessor (sibling or cousin)
342          *
343          */
344         RuleEditor ruleEditor = getRuleEditor(form);
345         String selectedPropKey = ruleEditor.getSelectedKey();
346 
347         // find parent
348         Node<RuleEditorTreeNode, String> parent = PropositionTreeUtil.findParentPropositionNode(ruleEditor.getEditTree().getRootElement(), selectedPropKey);
349 
350         // add new child at appropriate spot
351         if (parent != null) {
352             List<Node<RuleEditorTreeNode, String>> children = parent.getChildren();
353             for (int index = 0; index < children.size(); index++) {
354                 Node<RuleEditorTreeNode, String> child = children.get(index);
355                 // if our selected node is a simple proposition, add a new one after
356                 if (propKeyMatches(child, selectedPropKey) &&
357                         (isSimpleNode(child.getNodeType()) || (RuleEditorTreeNode.COMPOUND_NODE_TYPE.equalsIgnoreCase(child.getNodeType())))) {
358 
359                     //remove it from its current spot
360                     PropositionEditor parentProp = parent.getData().getProposition();
361                     PropositionEditor workingProp = parentProp.getCompoundEditors().remove(index / 2);
362                     if ((index > 0) && up) {
363                         parentProp.getCompoundEditors().add((index / 2) - 1, workingProp);
364                     } else if ((index < (children.size() - 1) && !up)) {
365                         parentProp.getCompoundEditors().add((index / 2) + 1, workingProp);
366                     }
367                     // redisplay the tree (editMode = true)
368                     this.getViewHelper(form).refreshInitTrees(ruleEditor);
369                     break;
370                 }
371             }
372         }
373     }
374 
375     public boolean isSimpleNode(String nodeType) {
376         if (KSSimplePropositionNode.NODE_TYPE.equalsIgnoreCase(nodeType) ||
377                 KSSimplePropositionEditNode.NODE_TYPE.equalsIgnoreCase(nodeType)) {
378             return true;
379         }
380         return false;
381     }
382 
383     @RequestMapping(params = "methodToCall=movePropositionLeft")
384     public ModelAndView movePropositionLeft(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
385                                             HttpServletRequest request, HttpServletResponse response)
386             throws Exception {
387 
388         /* Rough algorithm for moving a node up.
389          *
390          * find the following:
391          *   node := the selected node
392          *   parent := the selected node's parent, its containing node (via when true or when false relationship)
393          *   parentsOlderCousin := the parent's level-order predecessor (sibling or cousin)
394          *
395          */
396         RuleEditor ruleEditor = getRuleEditor(form);
397         String selectedpropKey = ruleEditor.getSelectedKey();
398 
399         // find agendaEditor.getAgendaItemLine().getRule().getPropositionTree().getRootElement()parent
400         Node<RuleEditorTreeNode, String> root = ruleEditor.getEditTree().getRootElement();
401         Node<RuleEditorTreeNode, String> parent = PropositionTreeUtil.findParentPropositionNode(root, selectedpropKey);
402         if ((parent != null) && (RuleEditorTreeNode.COMPOUND_NODE_TYPE.equalsIgnoreCase(parent.getNodeType()))) {
403             Node<RuleEditorTreeNode, String> granny = PropositionTreeUtil.findParentPropositionNode(root, parent.getData().getProposition().getKey());
404             if (!granny.equals(root)) {
405                 int oldIndex = findChildIndex(parent, selectedpropKey);
406                 int newIndex = findChildIndex(granny, parent.getData().getProposition().getKey());
407                 if (oldIndex >= 0 && newIndex >= 0) {
408                     PropositionEditor prop = parent.getData().getProposition().getCompoundEditors().remove(oldIndex / 2);
409                     granny.getData().getProposition().getCompoundEditors().add((newIndex / 2) + 1, prop);
410                     this.getViewHelper(form).refreshInitTrees(ruleEditor);
411                 }
412             }
413             // TODO: do we allow moving up to the root?
414             // we could add a new top level compound node, with current root as 1st child,
415             // and move the node to the second child.
416 
417         }
418         return getUIFModelAndView(form);
419     }
420 
421     @RequestMapping(params = "methodToCall=movePropositionRight")
422     public ModelAndView movePropositionRight(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
423                                              HttpServletRequest request, HttpServletResponse response)
424             throws Exception {
425         /* Rough algorithm for moving a node Right
426          * if the selected node is above a compound proposition, move it into the compound proposition as the first child
427          * if the node is above a simple proposition, do nothing.
428          * find the following:
429          *   node := the selected node
430          *   parent := the selected node's parent, its containing node
431          *   nextSibling := the node after the selected node
432          *
433          */
434         RuleEditor ruleEditor = getRuleEditor(form);
435         String selectedpropKey = ruleEditor.getSelectedKey();
436 
437         // find parent
438         Node<RuleEditorTreeNode, String> parent = PropositionTreeUtil.findParentPropositionNode(
439                 ruleEditor.getEditTree().getRootElement(), selectedpropKey);
440         if (parent != null) {
441             int index = findChildIndex(parent, selectedpropKey);
442             // if we are the last child, do nothing, otherwise
443             if (index >= 0 && index + 1 < parent.getChildren().size()) {
444                 Node<RuleEditorTreeNode, String> nextSibling = parent.getChildren().get(index + 2);
445                 // if selected node above a compound node, move it into it as first child
446                 if (RuleEditorTreeNode.COMPOUND_NODE_TYPE.equalsIgnoreCase(nextSibling.getNodeType())) {
447                     // remove selected node from it's current spot
448                     PropositionEditor prop = parent.getData().getProposition().getCompoundEditors().remove(index / 2);
449                     // add it to it's siblings children
450                     nextSibling.getData().getProposition().getCompoundEditors().add(0, prop);
451                     this.getViewHelper(form).refreshInitTrees(ruleEditor);
452                 }
453             }
454         }
455         return getUIFModelAndView(form);
456     }
457 
458     /**
459      * introduces a new compound proposition between the selected proposition and its parent.
460      * Additionally, it puts a new blank simple proposition underneath the compound proposition
461      * as a sibling to the selected proposition.
462      */
463     @RequestMapping(params = "methodToCall=togglePropositionSimpleCompound")
464     public ModelAndView togglePropositionSimpleCompound(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
465                                                         HttpServletRequest request, HttpServletResponse response)
466             throws Exception {
467 
468         RuleEditor ruleEditor = getRuleEditor(form);
469         String selectedPropKey = ruleEditor.getSelectedKey();
470 
471         PropositionTreeUtil.resetEditModeOnPropositionTree(ruleEditor);
472         RuleViewHelperService viewHelper = this.getViewHelper(form);
473 
474         if (!StringUtils.isBlank(selectedPropKey)) {
475             // find parent
476             Node<RuleEditorTreeNode, String> parent = PropositionTreeUtil.findParentPropositionNode(
477                     ruleEditor.getEditTree().getRootElement(), selectedPropKey);
478             if (parent != null) {
479 
480                 int index = findChildIndex(parent, selectedPropKey);
481 
482                 PropositionEditor propBo = parent.getChildren().get(index).getData().getProposition();
483 
484                 // create a new compound proposition
485                 PropositionEditor compound = viewHelper.createCompoundPropositionBoStub(propBo, true);
486                 compound.setDescription(KRMSConstants.PROP_COMP_DEFAULT_DESCR);
487                 compound.setEditMode(false);
488 
489                 if (parent.getData() == null) { // SPECIAL CASE: this is the only proposition in the tree
490                     ruleEditor.setProposition(compound);
491                 } else {
492                     PropositionEditor parentBo = parent.getData().getProposition();
493                     List<PropositionEditor> siblings = parentBo.getCompoundEditors();
494 
495                     int propIndex = -1;
496                     for (int i = 0; i < siblings.size(); i++) {
497                         if (propBo.getKey().equals(siblings.get(i).getKey())) {
498                             propIndex = i;
499                             break;
500                         }
501                     }
502 
503                     parentBo.getCompoundEditors().set(propIndex, compound);
504                     compound.getCompoundEditors().get(1).setEditMode(true);
505                     ruleEditor.setSelectedKey(compound.getCompoundComponents().get(1).getId());
506                 }
507             }
508         }
509 
510         viewHelper.refreshInitTrees(ruleEditor);
511         return getUIFModelAndView(form);
512     }
513 
514     @RequestMapping(params = "methodToCall=pasteProposition")
515     public ModelAndView pasteProposition(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
516                                          HttpServletRequest request, HttpServletResponse response)
517             throws Exception {
518 
519         boolean cutAction = true;
520         RuleEditor ruleEditor = getRuleEditor(form);
521         RuleViewHelperService viewHelper = this.getViewHelper(form);
522 
523         // get selected id
524         String selectedPropKey = ruleEditor.getSelectedKey();
525         if (StringUtils.isBlank(selectedPropKey)) {
526             return getUIFModelAndView(form);
527         }
528 
529         // get the id to move
530         String movePropKey = ruleEditor.getCutKey();
531         if (StringUtils.isBlank(movePropKey)) {
532             movePropKey = ruleEditor.getCopyKey();
533             cutAction = false;
534         }
535 
536         // check if selected and move is not the same
537         if (StringUtils.isNotBlank(movePropKey) && !selectedPropKey.equals(movePropKey)) {
538 
539             Node<RuleEditorTreeNode, String> root = ruleEditor.getEditTree().getRootElement();
540             PropositionEditor newParent = getNewParent(viewHelper, ruleEditor, selectedPropKey, root);
541             PropositionEditor oldParent = PropositionTreeUtil.findParentPropositionNode(root, movePropKey).getData().getProposition();
542             PropositionEditor workingProp = null;
543 
544             // cut or copy from old
545             if (oldParent != null) {
546                 List<PropositionEditor> children = oldParent.getCompoundEditors();
547                 for (int index = 0; index < children.size(); index++) {
548                     if (movePropKey.equalsIgnoreCase(children.get(index).getKey())) {
549                         if (cutAction) {
550                             workingProp = oldParent.getCompoundEditors().remove(index);
551                         } else {
552                             workingProp = viewHelper.copyProposition(oldParent.getCompoundEditors().get(index));
553                         }
554                         break;
555                     }
556                 }
557             }
558 
559             // add to new and refresh the tree
560             addProposition(selectedPropKey, newParent, workingProp);
561             viewHelper.refreshInitTrees(ruleEditor);
562         }
563 
564         // call the super method to avoid the agenda tree being reloaded from the db
565         return getUIFModelAndView(form);
566     }
567 
568     private PropositionEditor getNewParent(RuleViewHelperService viewHelper, RuleEditor ruleEditor, String selectedpropKey, Node<RuleEditorTreeNode, String> root) {
569         Node<RuleEditorTreeNode, String> parentNode = PropositionTreeUtil.findParentPropositionNode(root, selectedpropKey);
570         PropositionEditor newParent;
571         if (parentNode.equals(root)) {
572             // special case
573             // build new top level compound proposition,
574             // add existing as first child
575             // then paste cut node as 2nd child
576             newParent = viewHelper.createCompoundPropositionBoStub(
577                     root.getChildren().get(0).getData().getProposition(), false);
578             newParent.setEditMode(true);
579             ruleEditor.setProposition(newParent);
580         } else {
581             newParent = parentNode.getData().getProposition();
582         }
583         return newParent;
584     }
585 
586     private void addProposition(String selectedpropKey, PropositionEditor newParent, PropositionEditor workingProp) {
587         // add to new
588         if (newParent != null && workingProp != null) {
589             List<PropositionEditor> children = newParent.getCompoundEditors();
590             for (int index = 0; index < children.size(); index++) {
591                 if (selectedpropKey.equalsIgnoreCase(children.get(index).getKey())) {
592                     children.add(index + 1, workingProp);
593                     break;
594                 }
595             }
596         }
597     }
598 
599     @RequestMapping(params = "methodToCall=deleteProposition")
600     public ModelAndView deleteProposition(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
601                                           HttpServletRequest request, HttpServletResponse response)
602             throws Exception {
603         RuleEditor ruleEditor = getRuleEditor(form);
604         String selectedpropKey = ruleEditor.getSelectedKey();
605         Node<RuleEditorTreeNode, String> root = ruleEditor.getEditTree().getRootElement();
606 
607         Node<RuleEditorTreeNode, String> parentNode = PropositionTreeUtil.findParentPropositionNode(root, selectedpropKey);
608 
609         // what if it is the root?
610         if (parentNode != null && parentNode.getData() != null) { // it is not the root as there is a parent w/ a prop
611             PropositionEditor parent = parentNode.getData().getProposition();
612             if (parent != null) {
613                 List<PropositionEditor> children = (List<PropositionEditor>) parent.getCompoundComponents();
614                 for (int index = 0; index < children.size(); index++) {
615                     if (selectedpropKey.equalsIgnoreCase(children.get(index).getKey())) {
616                         parent.getCompoundComponents().remove(index);
617                         break;
618                     }
619                 }
620             }
621         } else { // no parent, it is the root
622             parentNode.getChildren().clear();
623             ruleEditor.getEditTree().setRootElement(null);
624             ruleEditor.setPropId(null);
625             ruleEditor.setProposition(null);
626         }
627 
628         this.getViewHelper(form).refreshInitTrees(ruleEditor);
629         return getUIFModelAndView(form);
630     }
631 
632     @RequestMapping(params = "methodToCall=updateCompoundOperator")
633     public ModelAndView updateCompoundOperator(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
634                                                HttpServletRequest request, HttpServletResponse response)
635             throws Exception {
636 
637         RuleViewHelperService viewHelper = this.getViewHelper(form);
638         RuleEditor ruleEditor = getRuleEditor(form);
639         String selectedpropKey = ruleEditor.getSelectedKey();
640         Node<RuleEditorTreeNode, String> parentNode = PropositionTreeUtil.findParentPropositionNode(ruleEditor.getEditTree().getRootElement(), selectedpropKey);
641         PropositionEditor parent = parentNode.getData().getProposition();
642 
643         PropositionEditor proposition = PropositionTreeUtil.findProposition(parentNode, selectedpropKey);
644         PropositionTreeUtil.setTypeForCompoundOpCode(parent, proposition.getCompoundOpCode());
645         parent.setDescription(viewHelper.resetDescription(parent));
646 
647         viewHelper.refreshInitTrees(ruleEditor);
648 
649         return getUIFModelAndView(form);
650     }
651 
652     @RequestMapping(params = "methodToCall=updateProposition")
653     public ModelAndView updateProposition(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
654                                           HttpServletRequest request, HttpServletResponse response)
655             throws Exception {
656         RuleEditor ruleEditor = getRuleEditor(form);
657         PropositionTreeUtil.resetNewProp((PropositionEditor) ruleEditor.getProposition());
658 
659         EnrolPropositionEditor proposition = (EnrolPropositionEditor) PropositionTreeUtil.getProposition(ruleEditor);
660 
661         //Resolve term if single course
662         //Reset the description
663         this.getViewHelper(form).resetDescription(proposition);
664 
665         //Remove the edit mode
666         PropositionTreeUtil.resetEditModeOnPropositionTree(ruleEditor);
667         this.getViewHelper(form).refreshInitTrees(ruleEditor);
668 
669         return getUIFModelAndView(form);
670     }
671 
672     @RequestMapping(params = "methodToCall=updateRule")
673     public ModelAndView updateRule(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
674                                    HttpServletRequest request, HttpServletResponse response)
675             throws Exception {
676 
677         MaintenanceDocumentForm document = (MaintenanceDocumentForm) form;
678         RuleManagementWrapper ruleWrapper = (RuleManagementWrapper) document.getDocument().getNewMaintainableObject().getDataObject();
679 
680         RuleEditor ruleEditor = getRuleEditor(form);
681 
682         this.getViewHelper(form).refreshViewTree(ruleEditor);
683         PropositionTreeUtil.resetNewProp((PropositionEditor) ruleEditor.getProposition());
684 
685         PropositionTreeUtil.resetEditModeOnPropositionTree(ruleEditor);
686         PropositionEditor proposition = PropositionTreeUtil.getProposition(ruleEditor);
687         this.getViewHelper(form).resetDescription(proposition);
688 
689 
690         //Replace edited rule with existing rule.
691         for (AgendaEditor agendaEditor : ruleWrapper.getAgendas()) {
692 
693             List<RuleEditor> ruleEditors = agendaEditor.getRuleEditors();
694             RuleEditor existingRule = AgendaUtilities.getSelectedRuleEditorByType(ruleEditors, ruleEditor.getTypeId());
695             if (existingRule != null) {
696                 ruleEditors.remove(existingRule);
697             }
698             ruleEditors.add(ruleEditor);
699         }
700 
701         form.getActionParameters().put(UifParameters.NAVIGATE_TO_PAGE_ID, "KRMS-AgendaMaintenance-Page");
702         return super.navigate(form, result, request, response);
703     }
704 
705     @RequestMapping(params = "methodToCall=updatePreview")
706     public ModelAndView updatePreview(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
707                                       HttpServletRequest request, HttpServletResponse response)
708             throws Exception {
709         RuleEditor ruleEditor = getRuleEditor(form);
710         ruleEditor.setSelectedTab("1");
711 
712         parseRuleExpression(ruleEditor);
713 
714         this.getViewHelper(form).refreshInitTrees(ruleEditor);
715         return getUIFModelAndView(form);
716     }
717 
718     @RequestMapping(params = "methodToCall=onTabSelect")
719     public ModelAndView onEditTabSelect(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
720                                       HttpServletRequest request, HttpServletResponse response)
721             throws Exception {
722 
723         RuleEditor ruleEditor = getRuleEditor(form);
724         parseRuleExpression(ruleEditor);
725 
726         this.getViewHelper(form).refreshInitTrees(ruleEditor);
727         return getUIFModelAndView(form);
728     }
729 
730     private void parseRuleExpression(RuleEditor ruleEditor) {
731         RuleLogicExpressionParser ruleLogicExpressionParser = new RuleLogicExpressionParser();
732         ruleLogicExpressionParser.setExpression(ruleEditor.getLogicArea());
733         List<String> propsAlpha = this.getPropositionKeys(new ArrayList<String>(), (PropositionEditor) ruleEditor.getProposition());
734 
735         //validate the expression
736         List<String> errorMessages = new ArrayList<String>();
737         boolean validExpression = ruleLogicExpressionParser.validateExpression(errorMessages, propsAlpha);
738 
739         //show errors and don't change anything else
740         if (!validExpression) {
741             for (int i = 0; i < errorMessages.size(); i++) {
742                 GlobalVariables.getMessageMap().putError("document.newMaintainableObject.dataObject.logicArea", errorMessages.get(i));
743             }
744             // reload page1
745             return;
746         }
747 
748         ruleEditor.setProposition(ruleLogicExpressionParser.parseExpressionIntoRule(ruleEditor));
749     }
750 
751     private List<String> getPropositionKeys(List<String> propositionKeys, PropositionEditor propositionEditor) {
752         propositionKeys.add(propositionEditor.getKey());
753         if (propositionEditor.getCompoundComponents() != null) {
754             for (PropositionEditor child : propositionEditor.getCompoundEditors()) {
755                 this.getPropositionKeys(propositionKeys, child);
756             }
757         }
758         return propositionKeys;
759     }
760 
761     @RequestMapping(params = "methodToCall=cancelEditProposition")
762     public ModelAndView cancelEditProposition(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
763                                               HttpServletRequest request, HttpServletResponse response)
764             throws Exception {
765 
766         RuleEditor ruleEditor = getRuleEditor(form);
767         PropositionEditor proposition = (PropositionEditor) ruleEditor.getProposition();
768 
769         //Reset the editing tree.
770         PropositionTreeUtil.cancelNewProp(proposition);
771         PropositionTreeUtil.resetEditModeOnPropositionTree(ruleEditor);
772         this.getViewHelper(form).refreshInitTrees(ruleEditor);
773 
774         return getUIFModelAndView(form);
775     }
776 
777     @RequestMapping(params = "methodToCall=cancelEditRule")
778     public ModelAndView cancelEditRule(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
779                                        HttpServletRequest request, HttpServletResponse response)
780             throws Exception {
781 
782         RuleEditor ruleEditor = getRuleEditor(form);
783         PropositionEditor proposition = (PropositionEditor) ruleEditor.getProposition();
784 
785         //Reset the editing tree.
786         if(proposition!=null){
787             PropositionTreeUtil.cancelNewProp(proposition);
788         }
789         PropositionTreeUtil.resetEditModeOnPropositionTree(ruleEditor);
790 
791         form.getActionParameters().put(UifParameters.NAVIGATE_TO_PAGE_ID, "KRMS-AgendaMaintenance-Page");
792         return super.navigate(form, result, request, response);
793     }
794 
795     @RequestMapping(params = "methodToCall=updatePropositionType")
796     public ModelAndView updatePropositionType(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
797                                               HttpServletRequest request, HttpServletResponse response)
798             throws Exception {
799 
800         PropositionEditor proposition = PropositionTreeUtil.getProposition(this.getRuleEditor(form));
801         configureProposition(form, proposition);
802 
803         return getUIFModelAndView(form);
804     }
805 
806     private void configureProposition(UifFormBase form, PropositionEditor proposition) {
807 
808         if (proposition != null) {
809 
810             if (PropositionType.COMPOUND.getCode().equalsIgnoreCase(proposition.getPropositionTypeCode())) {
811                 return;
812             }
813 
814             String propositionTypeId = proposition.getTypeId();
815             if (propositionTypeId == null) {
816                 proposition.setType(null);
817                 return;
818             }
819 
820             KrmsTypeDefinition type = KrmsRepositoryServiceLocator.getKrmsTypeRepositoryService().getTypeById(propositionTypeId);
821             if (type != null) {
822                 proposition.setType(type.getName());
823             }
824         }
825     }
826 
827     /**
828      * Test method for a controller that invokes a dialog lightbox.
829      *
830      * @param form     - test form
831      * @param result   - Spring form binding result
832      * @param request  - http request
833      * @param response - http response
834      * @return
835      * @throws Exception
836      */
837     @RequestMapping(params = "methodToCall=compareRules")
838     public ModelAndView compareRules(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
839                                      HttpServletRequest request, HttpServletResponse response) throws Exception {
840 
841         MaintenanceDocumentForm document = (MaintenanceDocumentForm) form;
842         Object dataObject = document.getDocument().getNewMaintainableObject().getDataObject();
843         if (dataObject instanceof RuleManagementWrapper) {
844             RuleManagementWrapper ruleWrapper = (RuleManagementWrapper) dataObject;
845             String ruleId = document.getActionParamaterValue("ruleKey");
846             RuleEditor ruleEditor = null;
847             if ((ruleId != null) && (StringUtils.isNotBlank(ruleId))) {
848                 //Get a specific ruleEditor based on the ruleId.
849                 ruleEditor = AgendaUtilities.getSelectedRuleEditor(ruleWrapper, ruleId);
850             } else {
851                 //Get the current editing ruleEditor.
852                 ruleEditor = ruleWrapper.getRuleEditor();
853             }
854 
855             //Build the compare rule tree
856             ruleWrapper.setCompareTree(this.getViewHelper(form).buildCompareTree(ruleEditor, ruleWrapper.getRefObjectId()));
857 
858         }
859 
860         // redirect back to client to display lightbox
861         return showDialog("compareRuleLightBox", form, request, response);
862     }
863 
864     protected RuleViewHelperService getViewHelper(UifFormBase form) {
865         return (RuleViewHelperService) KSControllerHelper.getViewHelperService(form);
866     }
867 //
868     @RequestMapping(params = "methodToCall=getSelectedKey")
869     public ModelAndView getSelectedKey(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
870                                        HttpServletRequest request, HttpServletResponse response) throws Exception {
871 
872         RuleViewHelperService viewHelper = this.getViewHelper(form);
873         String selectedKey = request.getParameter("selectedKey");
874 
875         RuleEditor ruleEditor = getRuleEditor(form);
876         String selectedpropKey = selectedKey;
877         ruleEditor.setSelectedKey(selectedpropKey);
878         //this.goToEditProposition()
879         return this.goToEditProposition(form,result, request, response);
880     }
881 
882 }