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