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.service.impl;
017
018import org.apache.commons.lang.StringUtils;
019import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
020import org.kuali.rice.core.api.util.tree.Tree;
021import org.kuali.rice.krad.uif.UifConstants;
022import org.kuali.rice.krad.uif.component.Component;
023import org.kuali.rice.krad.uif.container.Container;
024import org.kuali.rice.krad.uif.util.ComponentFactory;
025import org.kuali.rice.krad.uif.util.ComponentUtils;
026import org.kuali.rice.krad.uif.view.View;
027import org.kuali.rice.krad.util.BeanPropertyComparator;
028import org.kuali.rice.krad.util.GlobalVariables;
029import org.kuali.rice.krad.util.ObjectUtils;
030import org.kuali.rice.krad.web.form.MaintenanceDocumentForm;
031import org.kuali.rice.krms.api.KrmsConstants;
032import org.kuali.rice.krms.api.repository.LogicalOperator;
033import org.kuali.rice.krms.api.repository.RuleManagementService;
034import org.kuali.rice.krms.api.repository.proposition.PropositionType;
035import org.kuali.rice.krms.api.repository.term.TermDefinition;
036import org.kuali.rice.krms.api.repository.term.TermRepositoryService;
037import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition;
038import org.kuali.rice.krms.api.repository.type.KrmsTypeRepositoryService;
039import org.kuali.rice.krms.builder.ComponentBuilder;
040import org.kuali.rice.krms.dto.PropositionEditor;
041import org.kuali.rice.krms.dto.PropositionParameterEditor;
042import org.kuali.rice.krms.dto.RuleEditor;
043import org.kuali.rice.krms.dto.RuleManagementWrapper;
044import org.kuali.rice.krms.dto.TermEditor;
045import org.kuali.rice.krms.dto.TermParameterEditor;
046import org.kuali.rice.krms.impl.repository.KrmsRepositoryServiceLocator;
047import org.kuali.rice.krms.service.TemplateRegistry;
048import org.kuali.rice.krms.tree.RuleViewTreeBuilder;
049import org.kuali.rice.krms.tree.node.CompareTreeNode;
050import org.kuali.rice.krms.tree.RuleCompareTreeBuilder;
051import org.kuali.rice.krms.tree.RuleEditTreeBuilder;
052import org.kuali.rice.krms.tree.RulePreviewTreeBuilder;
053import org.kuali.rice.krms.util.KRMSConstants;
054import org.kuali.rice.krms.util.NaturalLanguageHelper;
055import org.kuali.rice.krms.util.PropositionTreeUtil;
056import org.kuali.rice.krms.dto.TemplateInfo;
057import org.kuali.rice.krms.service.RuleViewHelperService;
058import org.kuali.student.common.uif.service.impl.KSViewHelperServiceImpl;
059import org.kuali.student.r1.common.rice.StudentIdentityConstants;
060import org.kuali.student.r2.core.constants.KSKRMSServiceConstants;
061import org.springframework.beans.BeanUtils;
062
063import javax.xml.namespace.QName;
064import java.util.ArrayList;
065import java.util.Arrays;
066import java.util.HashMap;
067import java.util.List;
068import java.util.Map;
069
070/**
071 * Helpers Service for the Rule Pages.
072 *
073 * @author Kuali Student Team
074 */
075public class RuleViewHelperServiceImpl extends KSViewHelperServiceImpl implements RuleViewHelperService {
076
077    private transient RuleManagementService ruleManagementService;
078    private transient KrmsTypeRepositoryService krmsTypeRepositoryService;
079    private transient TermRepositoryService termRepositoryService;
080
081    private RuleCompareTreeBuilder compareTreeBuilder;
082    private RuleEditTreeBuilder editTreeBuilder;
083    private RulePreviewTreeBuilder previewTreeBuilder;
084    private RuleViewTreeBuilder viewTreeBuilder;
085
086    private NaturalLanguageHelper naturalLanguageHelper;
087
088    private static TemplateRegistry templateRegistry;
089
090    protected RuleEditor getRuleEditor(Object model) {
091        if (model instanceof MaintenanceDocumentForm) {
092            MaintenanceDocumentForm maintenanceDocumentForm = (MaintenanceDocumentForm) model;
093            Object dataObject = maintenanceDocumentForm.getDocument().getNewMaintainableObject().getDataObject();
094
095            if (dataObject instanceof RuleEditor) {
096                return (RuleEditor) dataObject;
097            } else if (dataObject instanceof RuleManagementWrapper) {
098                RuleManagementWrapper wrapper = (RuleManagementWrapper) dataObject;
099                return wrapper.getRuleEditor();
100            }
101        }
102        return null;
103    }
104
105    @Override
106    public TemplateInfo getTemplateForType(String type) {
107        return this.getTemplateRegistry().getTemplateForType(type);
108    }
109
110    @Override
111    protected void addCustomContainerComponents(View view, Object model, Container container) {
112        if (KRMSConstants.KRMS_PROPOSITION_DETAILSECTION_ID.equals(container.getId())) {
113            customizePropositionEditSection(view, model, container);
114        }
115    }
116
117    private void customizePropositionEditSection(View view, Object model, Container container) {
118        //Retrieve the current editing proposition if exists.
119        MaintenanceDocumentForm maintenanceDocumentForm = (MaintenanceDocumentForm) model;
120        Object dataObject = maintenanceDocumentForm.getDocument().getNewMaintainableObject().getDataObject();
121
122        RuleEditor ruleEditor = ((RuleManagementWrapper) dataObject).getRuleEditor();
123        PropositionEditor propEditor = PropositionTreeUtil.getProposition(ruleEditor);
124
125        List<Component> components = new ArrayList<Component>();
126        if (propEditor != null) {
127            //Retrieve the name of the xml component to display for the proposition type.
128            TemplateInfo template = this.getTemplateForType(propEditor.getType());
129
130            if (template != null && template.getComponentId() != null) {
131                Component component = ComponentFactory.getNewComponentInstance(template.getComponentId());
132                view.assignComponentIds(component);
133                if(container.getId().equals(maintenanceDocumentForm.getUpdateComponentId())){
134                    String nodePath = view.getDefaultBindingObjectPath() + "." + propEditor.getBindingPath();
135                    ComponentUtils.pushObjectToContext(component, UifConstants.ContextVariableNames.NODE_PATH, nodePath);
136                    ComponentUtils.prefixBindingPathNested(component, propEditor.getBindingPath());
137                }
138
139                //Add Proposition Type FieldGroup to Tree Node
140                components.add(component);
141            }
142
143            if (template != null && template.getConstantComponentId() != null) {
144                Component component = ComponentFactory.getNewComponentInstance(template.getConstantComponentId());
145                view.assignComponentIds(component);
146
147                //Add Proposition Type FieldGroup to Tree Node
148                components.add(component);
149            }
150        }
151
152        //Do not display if there are no components.
153        if (components.size() == 0) {
154            container.getHeader().setRender(false);
155        }
156
157        container.setItems(components);
158    }
159
160    /**
161     * Validate the rule.
162     *
163     * @param rule
164     * @return True if valid, false if not.
165     */
166    @Override
167    public Boolean validateRule(RuleEditor rule) {
168
169        boolean hasError = false;
170
171        //Return with error message if user is currently editing a proposition.
172        PropositionEditor proposition = PropositionTreeUtil.getProposition(rule);
173        if ((proposition != null) && (proposition.isEditMode())) {
174            GlobalVariables.getMessageMap().putErrorForSectionId(KRMSConstants.KRMS_PROPOSITION_DETAILSECTION_ID, KRMSConstants.KRMS_MSG_ERROR_RULE_PREVIEW);
175            hasError = true;
176        }
177
178        return hasError;
179    }
180
181    /**
182     * Validate the proposition.
183     *
184     * @param proposition
185     * @return True if valid, false if not.
186     */
187    @Override
188    public Boolean validateProposition(PropositionEditor proposition) {
189
190        // Retrieve the builder for the current proposition type.
191        ComponentBuilder builder = this.getTemplateRegistry().getComponentBuilderForType(proposition.getType());
192        if (builder != null) {
193            // Execute validation
194            builder.validate(proposition);
195        }
196
197        if (GlobalVariables.getMessageMap().getErrorMessages().isEmpty()) {
198            return Boolean.TRUE;
199        }
200
201        return Boolean.FALSE;
202    }
203
204    /**
205     * Initializes the proposition, populating the type and terms.
206     *
207     * @param propositionEditor
208     */
209    @Override
210    public void initPropositionEditor(PropositionEditor propositionEditor) {
211        if (PropositionType.SIMPLE.getCode().equalsIgnoreCase(propositionEditor.getPropositionTypeCode())) {
212
213            if (propositionEditor.getType() == null) {
214                KrmsTypeDefinition type = this.getKrmsTypeRepositoryService().getTypeById(propositionEditor.getTypeId());
215                propositionEditor.setType(type.getName());
216            }
217
218            ComponentBuilder builder = this.getTemplateRegistry().getComponentBuilderForType(propositionEditor.getType());
219            if (builder != null) {
220                Map<String, String> termParameters = this.getTermParameters(propositionEditor);
221                builder.resolveTermParameters(propositionEditor, termParameters);
222            }
223        } else {
224            for (PropositionEditor child : propositionEditor.getCompoundEditors()) {
225                initPropositionEditor(child);
226            }
227
228        }
229    }
230
231    /**
232     * Finalizes the proposition, setting the type and terms.
233     *
234     * @param propositionEditor
235     */
236    @Override
237    public void finPropositionEditor(PropositionEditor propositionEditor) {
238        if (PropositionType.SIMPLE.getCode().equalsIgnoreCase(propositionEditor.getPropositionTypeCode())) {
239
240            //Set the default operation and value
241            TemplateInfo template = this.getTemplateRegistry().getTemplateForType(propositionEditor.getType());
242            PropositionTreeUtil.getOperatorParameter(propositionEditor.getParameters()).setValue(template.getOperator());
243
244            if (!"n".equals(template.getValue())) {
245                PropositionTreeUtil.getConstantParameter(propositionEditor.getParameters()).setValue(template.getValue());
246            }
247
248            if (propositionEditor.getTerm() != null) {
249                TermDefinition.Builder termBuilder = TermDefinition.Builder.create(propositionEditor.getTerm());
250                PropositionTreeUtil.getTermParameter(propositionEditor.getParameters()).setTermValue(termBuilder.build());
251            }
252
253        } else {
254
255            //If not a simple node, recursively finalize the child proposition editors.
256            for (PropositionEditor child : propositionEditor.getCompoundEditors()) {
257                finPropositionEditor(child);
258            }
259
260        }
261    }
262
263    /**
264     * Create TermEditor from the TermDefinition objects to be used in the ui and return a map of
265     * the key and values of the term parameters.
266     *
267     * @param proposition
268     * @return
269     */
270    @Override
271    public Map<String, String> getTermParameters(PropositionEditor proposition) {
272
273        Map<String, String> termParameters = new HashMap<String, String>();
274        if (proposition.getTerm() == null) {
275            PropositionParameterEditor termParameter = PropositionTreeUtil.getTermParameter(proposition.getParameters());
276            if (termParameter != null) {
277                String termId = termParameter.getValue();
278                TermDefinition termDefinition = this.getTermRepositoryService().getTerm(termId);
279                proposition.setTerm(new TermEditor(termDefinition));
280            } else {
281                return termParameters;
282            }
283        }
284
285        for (TermParameterEditor parameter : proposition.getTerm().getEditorParameters()) {
286            termParameters.put(parameter.getName(), parameter.getValue());
287        }
288
289        return termParameters;
290    }
291
292    /**
293     * Clear the description and natural language on proposition editors.
294     *
295     * @param prop
296     * @return
297     */
298    @Override
299    public void resetDescription(PropositionEditor prop) {
300
301        //If proposition type is null, set description and term null
302        if (prop.getType() == null) {
303            prop.setDescription(StringUtils.EMPTY);
304            prop.setTerm(null);
305            prop.getNaturalLanguage().clear();
306            return;
307        }
308
309        //Build the new termParamters with the matching component builder.
310        if (PropositionType.SIMPLE.getCode().equalsIgnoreCase(prop.getPropositionTypeCode())) {
311            Map<String, String> termParameters = null;
312            ComponentBuilder builder = this.getTemplateRegistry().getComponentBuilderForType(prop.getType());
313            if (builder != null) {
314                termParameters = builder.buildTermParameters(prop);
315            }
316
317            List<TermParameterEditor> parameters = new ArrayList<TermParameterEditor>();
318            if (termParameters != null) {
319                for (Map.Entry<String, String> entry : termParameters.entrySet()) {
320
321                    TermParameterEditor parameterEditor = null;
322                    if (prop.getTerm().getParameters() != null) {
323                        for (TermParameterEditor parameter : prop.getTerm().getEditorParameters()) {
324
325                            if (entry.getKey().equals(parameter.getName())) {
326                                parameterEditor = parameter;
327                                parameterEditor.setValue(entry.getValue());
328                                break;
329                            }
330                        }
331                    }
332
333                    //Create a new parameter if not exist.
334                    if (parameterEditor == null) {
335                        parameterEditor = new TermParameterEditor();
336                        parameterEditor.setName(entry.getKey());
337                        parameterEditor.setValue(entry.getValue());
338                    }
339                    parameters.add(parameterEditor);
340                }
341            }
342
343            prop.getTerm().setParameters(parameters);
344
345            //Set the term specification if it doesn't exist.
346            if (prop.getTerm().getSpecification() == null) {
347                String termSpecName = this.getTemplateRegistry().getTermSpecNameForType(prop.getType());
348                prop.getTerm().setSpecification(getTermRepositoryService().getTermSpecificationByNameAndNamespace(termSpecName, KSKRMSServiceConstants.NAMESPACE_CODE));
349            }
350
351        } else {
352            prop.setTerm(null);
353        }
354
355        //Refresh the natural language.
356        prop.getNaturalLanguage().clear();
357    }
358
359    @Override
360    public void buildActions(RuleEditor ruleEditor) {
361    }
362
363    public void configurePropositionForType(PropositionEditor proposition) {
364
365        if (proposition != null) {
366
367            if (PropositionType.COMPOUND.getCode().equalsIgnoreCase(proposition.getPropositionTypeCode())) {
368                return;
369            }
370
371            String propositionTypeId = proposition.getTypeId();
372            if ((propositionTypeId == null) || (propositionTypeId.isEmpty())) {
373                proposition.setType(null);
374                return;
375            }
376
377            KrmsTypeDefinition type = KrmsRepositoryServiceLocator.getKrmsTypeRepositoryService().getTypeById(propositionTypeId);
378            if (type != null) {
379                proposition.setType(type.getName());
380            }
381
382            if (proposition.getTerm() == null) {
383                proposition.setTerm(new TermEditor());
384            }
385
386            String termSpecName = this.getTemplateRegistry().getTermSpecNameForType(proposition.getType());
387            proposition.getTerm().setSpecification(getTermRepositoryService().getTermSpecificationByNameAndNamespace(termSpecName, KSKRMSServiceConstants.NAMESPACE_CODE));
388
389        }
390    }
391
392    @Override
393    public void refreshInitTrees(RuleEditor rule) {
394
395        if (rule == null) {
396            return;
397        }
398
399        //Rebuild the trees
400        rule.setEditTree(this.getEditTreeBuilder().buildTree(rule));
401        rule.setPreviewTree(this.getPreviewTreeBuilder().buildTree(rule));
402    }
403
404    /**
405     * Rebuild the tree used for the view only trees.
406     *
407     * @param rule
408     */
409    @Override
410    public void refreshViewTree(RuleEditor rule) {
411
412        if (rule == null) {
413            return;
414        }
415
416        //Rebuild the trees
417        rule.setViewTree(this.getViewTreeBuilder().buildTree(rule));
418
419    }
420
421    @Override
422    public Tree<CompareTreeNode, String> buildCompareTree(RuleEditor original, RuleEditor compare) {
423
424        //Build the Tree
425        return this.getCompareTreeBuilder().buildTree(original, compare);
426
427    }
428
429    @Override
430    public Tree<CompareTreeNode, String> buildMultiViewTree(RuleEditor original, RuleEditor compare) {
431
432        //Build the Tree
433        return this.getCompareTreeBuilder().buildTree(original, compare);
434
435    }
436
437    /**
438     * Compare all the propositions in a rule tree with a parent rule tree. Returns false if any proposition's type
439     * or term parameters are not the same.
440     * <p/>
441     * Apart from the type and termparameters, all other detail is derived from the typeid and therefore not included in
442     * the comparison.     *
443     *
444     * @param original
445     * @return boolean
446     * @throws Exception
447     */
448    @Override
449    public Boolean compareRules(RuleEditor original) {
450
451        //Do null check on propositions.
452        RuleEditor compareEditor = original.getParent();
453        if ((compareEditor == null) || (compareEditor.getProposition() == null)) {
454            if (original.getProposition() != null) {
455                return false; //if compare is null and original is not, they differ.
456            } else {
457                return true; //both of them are null.
458            }
459        } else if (original.getProposition() == null) {
460            return false;
461        }
462
463        //Compare Root Proposition Type and if the same test recursively
464        if (original.getProposition().getTypeId().equals(compareEditor.getProposition().getTypeId())) {
465            return compareProposition(original.getPropositionEditor(), compareEditor.getPropositionEditor());
466        } else {
467            return false;
468        }
469    }
470
471    /**
472     * Method to handle the proposition comparison recursively.
473     *
474     * @param original
475     * @param compare
476     * @return true if proposition are the same.
477     */
478    @Override
479    public Boolean compareProposition(PropositionEditor original, PropositionEditor compare) {
480        //Compare the proposition
481        BeanPropertyComparator propositionComparator = new BeanPropertyComparator(Arrays.asList("typeId"));
482        if (propositionComparator.compare(original, compare) != 0) {
483            return false;
484        }
485
486        //Compare the term values
487        if (PropositionType.SIMPLE.getCode().equalsIgnoreCase(original.getPropositionTypeCode())) {
488            TermEditor term = new TermEditor(PropositionTreeUtil.getTermParameter(compare.getParameters()).getTermValue());
489            if (!compareTerm(original.getTerm().getEditorParameters(), term.getEditorParameters())) {
490                return false;
491            }
492        }
493
494        //Compare the compound propositions.
495        return compareCompoundProposition(original.getCompoundEditors(), compare.getCompoundEditors());
496    }
497
498    /**
499     * Compare all the keys and values of the term parameter. Returns false if any of the keys (names) or
500     * values of the term paramters is not the same.
501     *
502     * @param original list of term parameters for current term
503     * @param compare  list of term paramters to compare with.
504     * @return true if all names and values are the same.
505     */
506    @Override
507    public Boolean compareTerm(List<TermParameterEditor> original, List<TermParameterEditor> compare) {
508
509        //If the sizes doesn't match, they are not same.
510        int originalSize = original == null ? 0 : original.size();
511        if (originalSize != (compare == null ? 0 : compare.size())) {
512            return false;
513        } else if (originalSize > 0) {
514
515            //Compare the compound propositions.
516            BeanPropertyComparator termComparator = new BeanPropertyComparator(Arrays.asList("name","value"));
517            for (int index = 0; index < originalSize; index++) {
518                if (termComparator.compare(original.get(index), compare.get(index)) != 0) {
519                    return false;
520                }
521            }
522        }
523
524        return true;
525
526    }
527
528    /**
529     * Recursively compare child propositions.
530     *
531     * @param original
532     * @param compare
533     * @return
534     */
535    @Override
536    public Boolean compareCompoundProposition(List<PropositionEditor> original, List<PropositionEditor> compare) {
537
538        //If the sizes doesn't match, they are not same.
539        int originalSize = original == null ? 0 : original.size();
540        if (originalSize != (compare == null ? 0 : compare.size())) {
541            return false;
542        } else if (originalSize > 0) {
543
544            //Compare the compound propositions.
545            for (int index = 0; index < originalSize; index++) {
546                if (!compareProposition(original.get(index), compare.get(index))) {
547                    return false;
548                }
549            }
550        }
551
552        return true;
553    }
554
555    /**
556     * Make a new copy of the current proposition including the compounds.
557     * <p/>
558     * The deepcopy is done to make sure that create a full copy and does not only copy the references.
559     *
560     * @param oldProposition
561     * @return
562     */
563    @Override
564    public PropositionEditor copyProposition(PropositionEditor oldProposition) {
565        try {
566            PropositionEditor newProposition = this.copyPropositionEditor(oldProposition);
567
568            //Use a deepcopy to create new references to inner objects such as string.
569            return (PropositionEditor) ObjectUtils.deepCopy(newProposition);
570        } catch (Exception e) {
571            return null;
572        }
573    }
574
575    /**
576     * Used when the user clicked the copy button. It creates a new copy of the proposition with all the related
577     * compound propositions.
578     * <p/>
579     * The compound propositions is handled recursively.
580     *
581     * @param oldProposition
582     * @return
583     */
584    protected PropositionEditor copyPropositionEditor(PropositionEditor oldProposition) {
585        PropositionEditor newProposition;
586        try {
587            newProposition = this.getPropositionEditorClass().newInstance();
588        } catch (Exception e) {
589            newProposition = new PropositionEditor();
590        }
591        BeanUtils.copyProperties(oldProposition, newProposition, new String[]{"key", "id", "term", "parameters"});
592
593        if (!oldProposition.getPropositionTypeCode().equals("C")) {
594            List<PropositionParameterEditor> propositionParameterEditors = new ArrayList<PropositionParameterEditor>();
595            for (PropositionParameterEditor parm : oldProposition.getParameters()) {
596                PropositionParameterEditor newParm = new PropositionParameterEditor();
597                BeanUtils.copyProperties(parm, newParm, new String[]{"termValue", "id", "versionNumber"});
598                propositionParameterEditors.add(newParm);
599            }
600
601            newProposition.setParameters(propositionParameterEditors);
602
603            TermEditor termEditor = new TermEditor();
604            List<TermParameterEditor> termParameterEditors = new ArrayList<TermParameterEditor>();
605           if( oldProposition.getTerm() != null) {
606            BeanUtils.copyProperties(oldProposition.getTerm(), termEditor, new String[]{"id", "versionNumber", "parameters"});
607            for (TermParameterEditor termParm : oldProposition.getTerm().getEditorParameters()) {
608                TermParameterEditor newTermParm = new TermParameterEditor();
609                BeanUtils.copyProperties(termParm, newTermParm, new String[]{"id", "versionNumber"});
610                termParameterEditors.add(newTermParm);
611            }
612           }
613            termEditor.setParameters(termParameterEditors);
614
615            newProposition.setTerm(termEditor);
616            this.resetDescription(newProposition);
617        }
618
619        if (newProposition.getCompoundEditors() != null) {
620            List<PropositionEditor> props = new ArrayList<PropositionEditor>();
621            for (PropositionEditor prop : newProposition.getCompoundEditors()) {
622                props.add(this.copyPropositionEditor(prop));
623            }
624            newProposition.setCompoundEditors(props);
625        }
626
627
628        return newProposition;
629    }
630
631    @Override
632    public PropositionEditor createCompoundPropositionBoStub(PropositionEditor existing, boolean addNewChild) {
633        try {
634            PropositionEditor compound = PropositionTreeUtil.createCompoundPropositionBoStub(existing, addNewChild, this.getPropositionEditorClass());
635            this.setTypeForCompoundOpCode(compound, LogicalOperator.AND.getCode());
636            return compound;
637        } catch (Exception e) {
638            return null;
639        }
640    }
641
642    @Override
643    public void setTypeForCompoundOpCode(PropositionEditor proposition, String compoundOpCode) {
644        //Return as quickly as possible for performance.
645        if (compoundOpCode.equals(proposition.getCompoundOpCode())) {
646            return;
647        }
648
649        //Clear the natural language so the the tree builder can rebuild it.
650        proposition.getNaturalLanguage().clear();
651        proposition.setCompoundOpCode(compoundOpCode);
652    }
653
654    /**
655     * Creates a new instance of a simple proposition.
656     *
657     * @param sibling
658     * @return
659     */
660    @Override
661    public PropositionEditor createSimplePropositionBoStub(PropositionEditor sibling) {
662        try {
663            return PropositionTreeUtil.createSimplePropositionBoStub(sibling, this.getPropositionEditorClass());
664        } catch (Exception e) {
665            return null;
666        }
667    }
668
669    /**
670     * Override this method to return a different class type if you need to use a different propositoin editor class.
671     *
672     * @return
673     */
674    public Class<? extends PropositionEditor> getPropositionEditorClass() {
675        return PropositionEditor.class;
676    }
677
678    protected RuleManagementService getRuleManagementService() {
679        if (ruleManagementService == null) {
680            ruleManagementService = (RuleManagementService) GlobalResourceLoader.getService(QName.valueOf("ruleManagementService"));
681        }
682        return ruleManagementService;
683    }
684
685    protected RuleCompareTreeBuilder getCompareTreeBuilder() {
686        if (compareTreeBuilder == null) {
687            compareTreeBuilder = new RuleCompareTreeBuilder();
688        }
689        return compareTreeBuilder;
690    }
691
692    protected RuleEditTreeBuilder getEditTreeBuilder() {
693        if (editTreeBuilder == null) {
694            editTreeBuilder = new RuleEditTreeBuilder();
695        }
696        return editTreeBuilder;
697    }
698
699    protected RulePreviewTreeBuilder getPreviewTreeBuilder() {
700        if (previewTreeBuilder == null) {
701            previewTreeBuilder = new RulePreviewTreeBuilder();
702        }
703        return previewTreeBuilder;
704    }
705
706    protected RuleViewTreeBuilder getViewTreeBuilder() {
707        if (viewTreeBuilder == null) {
708            viewTreeBuilder = new RuleViewTreeBuilder();
709        }
710        return viewTreeBuilder;
711    }
712
713    protected NaturalLanguageHelper getNaturalLanguageHelper() {
714        if (naturalLanguageHelper == null) {
715            naturalLanguageHelper = new NaturalLanguageHelper();
716            naturalLanguageHelper.setRuleManagementService(this.getRuleManagementService());
717        }
718        return naturalLanguageHelper;
719    }
720
721    protected TemplateRegistry getTemplateRegistry() {
722        if (templateRegistry == null) {
723            templateRegistry = (TemplateRegistry) GlobalResourceLoader.getService(new QName("http://student.kuali.org/wsdl/templateResolverService", "templateResolverService"));
724        }
725        return templateRegistry;
726    }
727
728    protected KrmsTypeRepositoryService getKrmsTypeRepositoryService() {
729        if (krmsTypeRepositoryService == null) {
730            krmsTypeRepositoryService = (KrmsTypeRepositoryService) GlobalResourceLoader.getService(new QName(KrmsConstants.Namespaces.KRMS_NAMESPACE_2_0, "krmsTypeRepositoryService"));
731        }
732        return krmsTypeRepositoryService;
733    }
734
735    public TermRepositoryService getTermRepositoryService() {
736        if (termRepositoryService == null) {
737            termRepositoryService = (TermRepositoryService) GlobalResourceLoader.getService(new QName(KrmsConstants.Namespaces.KRMS_NAMESPACE_2_0, "termRepositoryService"));
738        }
739        return termRepositoryService;
740    }
741
742}