001/**
002 * Copyright 2005-2016 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.impl.repository;
017
018import org.apache.commons.lang.StringUtils;
019import org.apache.commons.lang.builder.EqualsBuilder;
020import org.kuali.rice.core.api.CoreConstants;
021import org.kuali.rice.core.api.criteria.GenericQueryResults;
022import org.kuali.rice.core.api.criteria.Predicate;
023import org.kuali.rice.core.api.criteria.QueryByCriteria;
024import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
025import org.kuali.rice.krad.service.BusinessObjectService;
026import org.kuali.rice.krad.service.KRADServiceLocator;
027import org.kuali.rice.krad.service.SequenceAccessorService;
028import org.kuali.rice.krms.api.repository.NaturalLanguageTree;
029import org.kuali.rice.krms.api.repository.RuleManagementService;
030import org.kuali.rice.krms.api.repository.TranslateBusinessMethods;
031import org.kuali.rice.krms.api.repository.action.ActionDefinition;
032import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition;
033import org.kuali.rice.krms.api.repository.agenda.AgendaItemDefinition;
034import org.kuali.rice.krms.api.repository.context.ContextDefinition;
035import org.kuali.rice.krms.api.repository.language.NaturalLanguageTemplate;
036import org.kuali.rice.krms.api.repository.language.NaturalLanguageTemplaterContract;
037import org.kuali.rice.krms.api.repository.language.NaturalLanguageUsage;
038import org.kuali.rice.krms.api.repository.proposition.PropositionDefinition;
039import org.kuali.rice.krms.api.repository.proposition.PropositionParameter;
040import org.kuali.rice.krms.api.repository.proposition.PropositionParameterType;
041import org.kuali.rice.krms.api.repository.proposition.PropositionType;
042import org.kuali.rice.krms.api.repository.reference.ReferenceObjectBinding;
043import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
044import org.kuali.rice.krms.api.repository.term.TermDefinition;
045import org.kuali.rice.krms.api.repository.term.TermRepositoryService;
046import org.kuali.rice.krms.impl.repository.language.SimpleNaturalLanguageTemplater;
047
048import java.util.ArrayList;
049import java.util.Arrays;
050import java.util.Collections;
051import java.util.LinkedHashSet;
052import java.util.LinkedList;
053import java.util.List;
054import java.util.Set;
055
056import static org.kuali.rice.core.api.criteria.PredicateFactory.in;
057
058/**
059 * The implementation of {@link RuleManagementService} operations facilitate management of rules and
060 * associated information.
061 *
062 * @author Kuali Rice Team (rice.collab@kuali.org)
063 */
064public class RuleManagementServiceImpl extends RuleRepositoryServiceImpl implements RuleManagementService {
065
066    private ReferenceObjectBindingBoService referenceObjectBindingBoService = new ReferenceObjectBindingBoServiceImpl();
067    private AgendaBoService agendaBoService = new AgendaBoServiceImpl();
068    private RuleBoService ruleBoService = new RuleBoServiceImpl();
069    private ActionBoService actionBoService = new ActionBoServiceImpl();
070    private PropositionBoService propositionBoService = new PropositionBoServiceImpl();
071    private NaturalLanguageUsageBoService naturalLanguageUsageBoService = new NaturalLanguageUsageBoServiceImpl();
072    private NaturalLanguageTemplateBoService naturalLanguageTemplateBoService = new NaturalLanguageTemplateBoServiceImpl();
073    private ContextBoService contextBoService = new ContextBoServiceImpl();
074    private NaturalLanguageTemplaterContract templater = new SimpleNaturalLanguageTemplater();
075    private TermRepositoryService termRepositoryService = new TermBoServiceImpl();
076    private SequenceAccessorService sequenceAccessorService = null;
077    private TranslateBusinessMethods translationBusinessMethods = null;
078
079    /**
080     * Fields to ignore when calling reflection-based equals in
081     * {@link #isSame(org.kuali.rice.krms.api.repository.agenda.AgendaDefinition, org.kuali.rice.krms.api.repository.agenda.AgendaDefinition)}
082     */
083    private static final List<String> isSameIgnoreFields = Arrays.asList(
084            AgendaDefinition.Elements.AGENDA_ID,
085            CoreConstants.CommonElements.VERSION_NUMBER,
086            CoreConstants.CommonElements.FUTURE_ELEMENTS
087    );
088
089    /**
090     * get the {@link ReferenceObjectBindingBoService}
091     * @return the {@link ReferenceObjectBindingBoService}
092     */
093    public ReferenceObjectBindingBoService getReferenceObjectBindingBoService() {
094        return referenceObjectBindingBoService;
095    }
096
097    /**
098     * set the {@link ReferenceObjectBindingBoService}
099     * @param referenceObjectBindingBoService the {@link ReferenceObjectBindingBoService} to set
100     */
101    public void setReferenceObjectBindingBoService(ReferenceObjectBindingBoService referenceObjectBindingBoService) {
102        this.referenceObjectBindingBoService = referenceObjectBindingBoService;
103    }
104
105    /**
106     * get the {@link AgendaBoService}
107     * @return the {@link AgendaBoService}
108     */
109    public AgendaBoService getAgendaBoService() {
110        return agendaBoService;
111    }
112
113    /**
114     * set the {@link AgendaBoService}
115     * @param agendaBoService the {@link AgendaBoService} to set
116     */
117    public void setAgendaBoService(AgendaBoService agendaBoService) {
118        this.agendaBoService = agendaBoService;
119    }
120
121    /**
122     * get the {@link RuleBoService}
123     * @return the {@link RuleBoService}
124     */
125    public RuleBoService getRuleBoService() {
126        return ruleBoService;
127    }
128
129    /**
130     * set the {@link RuleBoService}
131     * @param ruleBoService the {@link RuleBoService} to set
132     */
133    public void setRuleBoService(RuleBoService ruleBoService) {
134        this.ruleBoService = ruleBoService;
135    }
136
137    /**
138     * get the {@link PropositionBoService}
139     * @return the {@link PropositionBoService}
140     */
141    public PropositionBoService getPropositionBoService() {
142        return propositionBoService;
143    }
144
145    /**
146     * set the {@link PropositionBoService}
147     * @param propositionBoService the {@link PropositionBoService} to set
148     */
149    public void setPropositionBoService(PropositionBoService propositionBoService) {
150        this.propositionBoService = propositionBoService;
151    }
152
153    /**
154     * set the {@link NaturalLanguageUsageBoService}
155     * @return the {@link NaturalLanguageUsageBoService}
156     */
157    public NaturalLanguageUsageBoService getNaturalLanguageUsageBoService() {
158        return naturalLanguageUsageBoService;
159    }
160
161    /**
162     * set the {@link NaturalLanguageUsageBoService}
163     * @param naturalLanguageUsageBoService the {@link NaturalLanguageUsageBoService} to set
164     */
165    public void setNaturalLanguageUsageBoService(NaturalLanguageUsageBoService naturalLanguageUsageBoService) {
166        this.naturalLanguageUsageBoService = naturalLanguageUsageBoService;
167    }
168
169    /**
170     * get the {@link NaturalLanguageTemplateBoService}
171     * @return the {@link NaturalLanguageTemplateBoService}
172     */
173    public NaturalLanguageTemplateBoService getNaturalLanguageTemplateBoService() {
174        return naturalLanguageTemplateBoService;
175    }
176
177    /**
178     * set the {@link NaturalLanguageTemplateBoService}
179     * @param naturalLanguageTemplateBoService the {@link NaturalLanguageTemplateBoService} to set
180     */
181    public void setNaturalLanguageTemplateBoService(NaturalLanguageTemplateBoService naturalLanguageTemplateBoService) {
182        this.naturalLanguageTemplateBoService = naturalLanguageTemplateBoService;
183    }
184
185    /**
186     * get the {@link ContextBoService}
187     * @return the {@link ContextBoService}
188     */
189    public ContextBoService getContextBoService() {
190        return contextBoService;
191    }
192
193    /**
194     * set the {@link ContextBoService}
195     * @param contextBoService the {@link ContextBoService} to set
196     */
197    public void setContextBoService(ContextBoService contextBoService) {
198        this.contextBoService = contextBoService;
199    }
200
201    /**
202     * get the {@link ActionBoService}
203     * @return the {@link ActionBoService}
204     */
205    public ActionBoService getActionBoService() {
206        return actionBoService;
207    }
208
209    /**
210     * Set the {@link ActionBoService}
211     * @param actionBoService the {@link ActionBoService} to set
212     */
213    public void setActionBoService(ActionBoService actionBoService) {
214        this.actionBoService = actionBoService;
215    }
216
217    /**
218     * get the {@link NaturalLanguageTemplaterContract}
219     * @return the {@link NaturalLanguageTemplaterContract}
220     */
221    public NaturalLanguageTemplaterContract getTemplater() {
222        return templater;
223    }
224
225    /**
226     * set the {@link NaturalLanguageTemplaterContract}
227     * @param templater the {@link NaturalLanguageTemplaterContract} to set
228     */
229    public void setTemplater(NaturalLanguageTemplaterContract templater) {
230        this.templater = templater;
231    }
232
233    /**
234     * get the {@link TermRepositoryService}
235     * @return the {@link TermRepositoryService}
236     */
237    public TermRepositoryService getTermRepositoryService() {
238        return termRepositoryService;
239    }
240
241    /**
242     * Set the {@link TermRepositoryService}
243     * @param termRepositoryService the {@link TermRepositoryService} to set
244     */
245    public void setTermRepositoryService(TermRepositoryService termRepositoryService) {
246        this.termRepositoryService = termRepositoryService;
247    }
248
249    /**
250     * get the {@link SequenceAccessorService}
251     * @return the {@link SequenceAccessorService}
252     */
253    public SequenceAccessorService getSequenceAccessorService() {
254        if (this.sequenceAccessorService == null) {
255            this.sequenceAccessorService = KRADServiceLocator.getSequenceAccessorService();
256        }
257        return sequenceAccessorService;
258    }
259
260    /**
261     * set the {@link SequenceAccessorService}
262     * @param sequenceAccessorService the {@link SequenceAccessorService} to set
263     */
264    public void setSequenceAccessorService(SequenceAccessorService sequenceAccessorService) {
265        this.sequenceAccessorService = sequenceAccessorService;
266    }
267
268    /**
269     * get the {@link TranslateBusinessMethods}
270     * @return the current {@link TranslateBusinessMethods}
271     */
272    public TranslateBusinessMethods getTranslateBusinessMethods() {
273        if(translationBusinessMethods  == null) {
274            this.translationBusinessMethods  = new TranslationUtility(this, getTermRepositoryService(), this.templater);
275        }
276        return this.translationBusinessMethods ;
277    }
278
279    /**
280     * set the {@link TranslateBusinessMethods}
281     * @param translationBusinessMethods the {@link TranslateBusinessMethods} to set
282     */
283    public void setTranslationBusinessMethods (TranslateBusinessMethods  translationBusinessMethods) {
284        this.translationBusinessMethods  = translationBusinessMethods;
285    }
286
287    ////
288    //// reference object binding methods
289    ////
290
291    @Override
292    public ReferenceObjectBinding createReferenceObjectBinding(ReferenceObjectBinding referenceObjectDefinition)
293            throws RiceIllegalArgumentException {
294        //Set the id if it doesn't exist.
295        if (referenceObjectDefinition.getId() == null) {
296            String referenceObjectBindingId = getSequenceAccessorService().getNextAvailableSequenceNumber("KRMS_REF_OBJ_KRMS_OBJ_S", ReferenceObjectBindingBo.class).toString();
297            ReferenceObjectBinding.Builder refBldr = ReferenceObjectBinding.Builder.create(referenceObjectDefinition);
298            refBldr.setId(referenceObjectBindingId);
299            referenceObjectDefinition = refBldr.build();
300        }
301
302        return referenceObjectBindingBoService.createReferenceObjectBinding(referenceObjectDefinition);
303    }
304
305    @Override
306    public ReferenceObjectBinding getReferenceObjectBinding(String id) throws RiceIllegalArgumentException {
307        return referenceObjectBindingBoService.getReferenceObjectBinding(id);
308    }
309
310    @Override
311    public List<ReferenceObjectBinding> getReferenceObjectBindings(List<String> ids) throws RiceIllegalArgumentException {
312        if (ids == null) {
313            throw new IllegalArgumentException("reference binding object ids must not be null");
314        }
315
316        // Fetch BOs
317        List<ReferenceObjectBindingBo> bos = null;
318
319        if (ids.size() == 0) {
320            bos = Collections.emptyList();
321        } else {
322            QueryByCriteria.Builder qBuilder = QueryByCriteria.Builder.create();
323            List<Predicate> pList = new ArrayList<Predicate>();
324            qBuilder.setPredicates(in("id", ids.toArray()));
325            GenericQueryResults<ReferenceObjectBindingBo> results = getCriteriaLookupService().lookup(ReferenceObjectBindingBo.class, qBuilder.build());
326
327            bos = results.getResults();
328        }
329
330        // Translate BOs
331        List<ReferenceObjectBinding> bindings = new LinkedList<ReferenceObjectBinding>();
332        for (ReferenceObjectBindingBo bo : bos) {
333            ReferenceObjectBinding binding = ReferenceObjectBindingBo.to(bo);
334            bindings.add(binding);
335        }
336
337        return Collections.unmodifiableList(bindings);
338    }
339
340    @Override
341    public List<ReferenceObjectBinding> findReferenceObjectBindingsByReferenceObject(String referenceObjectReferenceDiscriminatorType,
342            String referenceObjectId)
343            throws RiceIllegalArgumentException {
344        if (referenceObjectReferenceDiscriminatorType == null) {
345            throw new RiceIllegalArgumentException("reference binding object discriminator type must not be null");
346        }
347
348        if (referenceObjectId == null) {
349            throw new RiceIllegalArgumentException("reference object id must not be null");
350        }
351
352        List<ReferenceObjectBinding> list = new ArrayList<ReferenceObjectBinding>();
353        for (ReferenceObjectBinding binding : this.referenceObjectBindingBoService.findReferenceObjectBindingsByReferenceObject(referenceObjectId)) {
354            if (binding.getReferenceDiscriminatorType().equals(referenceObjectReferenceDiscriminatorType)) {
355                list.add(binding);
356            }
357        }
358
359        return list;
360    }
361    
362    @Override
363    public List<ReferenceObjectBinding> findReferenceObjectBindingsByReferenceDiscriminatorType(String referenceObjectReferenceDiscriminatorType) throws RiceIllegalArgumentException {
364        return referenceObjectBindingBoService.findReferenceObjectBindingsByReferenceDiscriminatorType(referenceObjectReferenceDiscriminatorType);
365    }
366
367    @Override
368    public List<ReferenceObjectBinding> findReferenceObjectBindingsByKrmsDiscriminatorType(String referenceObjectKrmsDiscriminatorType) throws RiceIllegalArgumentException {
369        return referenceObjectBindingBoService.findReferenceObjectBindingsByKrmsDiscriminatorType(referenceObjectKrmsDiscriminatorType);
370    }
371
372    @Override
373    public List<ReferenceObjectBinding> findReferenceObjectBindingsByKrmsObject(String krmsObjectId) throws RiceIllegalArgumentException {
374        return referenceObjectBindingBoService.findReferenceObjectBindingsByKrmsObject(krmsObjectId);
375    }
376
377    @Override
378    public void updateReferenceObjectBinding(ReferenceObjectBinding referenceObjectBindingDefinition)
379            throws RiceIllegalArgumentException {
380        referenceObjectBindingBoService.updateReferenceObjectBinding(referenceObjectBindingDefinition);
381    }
382
383    @Override
384    public void deleteReferenceObjectBinding(String id) throws RiceIllegalArgumentException {
385        referenceObjectBindingBoService.deleteReferenceObjectBinding(id);
386    }
387
388    @Override
389    public List<String> findReferenceObjectBindingIds(QueryByCriteria queryByCriteria) throws RiceIllegalArgumentException {
390        return referenceObjectBindingBoService.findReferenceObjectBindingIds(queryByCriteria);
391    }
392
393    ////
394    //// agenda
395    //// 
396    @Override
397    public AgendaDefinition createAgenda(AgendaDefinition agendaDefinition) throws RiceIllegalArgumentException {
398        return agendaBoService.createAgenda(agendaDefinition);
399    }
400
401    @Override
402    public AgendaDefinition getAgendaByNameAndContextId(String name, String contextId) {
403        return this.agendaBoService.getAgendaByNameAndContextId(name, contextId);
404    }
405
406    @Override
407    public AgendaDefinition findCreateAgenda(AgendaDefinition agendaDefinition) throws RiceIllegalArgumentException {
408        AgendaDefinition existing = this.getAgendaByNameAndContextId(agendaDefinition.getName(), agendaDefinition.getContextId());
409
410        if (existing != null) {
411            existing = this.updateAgendaIfNeeded(agendaDefinition, existing);
412            return existing;
413        }
414
415        return this.createAgenda(agendaDefinition);
416    }
417
418    private AgendaDefinition updateAgendaIfNeeded(AgendaDefinition agenda, AgendaDefinition existing) {
419        if (this.isSame(agenda, existing)) {
420            return existing;
421        }
422
423        AgendaDefinition.Builder bldr = AgendaDefinition.Builder.create(existing);
424        bldr.setActive(agenda.isActive());
425        bldr.setAttributes(agenda.getAttributes());
426        bldr.setContextId(agenda.getContextId());
427
428        if (agenda.getFirstItemId() != null) {
429            bldr.setFirstItemId(agenda.getFirstItemId());
430        }
431
432        bldr.setTypeId(agenda.getTypeId());
433        this.updateAgenda(bldr.build());
434
435        return this.getAgenda(existing.getId());
436    }
437
438    /**
439     * Compares two {@link AgendaDefinition}s for equality, ignoring certain fields defined by
440     * {@link #isSameIgnoreFields}.
441     *
442     * @param agenda one agenda
443     * @param existing another agenda
444     * @return true if the two agendas are considered to be the same
445     */
446    private boolean isSame(AgendaDefinition agenda, AgendaDefinition existing) {
447        return EqualsBuilder.reflectionEquals(agenda, existing, isSameIgnoreFields);
448    }
449
450    @Override
451    public AgendaDefinition getAgenda(String id) throws RiceIllegalArgumentException {
452        return agendaBoService.getAgendaByAgendaId(id);
453    }
454
455    @Override
456    public List<AgendaDefinition> getAgendasByContext(String contextId) throws RiceIllegalArgumentException {
457        return agendaBoService.getAgendasByContextId(contextId);
458    }
459
460    @Override
461    public void updateAgenda(AgendaDefinition agendaDefinition) throws RiceIllegalArgumentException {
462        agendaBoService.updateAgenda(agendaDefinition);
463    }
464
465    @Override
466    public void deleteAgenda(String id) throws RiceIllegalArgumentException {
467        agendaBoService.deleteAgenda(id);
468    }
469
470    @Override
471    public List<AgendaDefinition> getAgendasByType(String typeId) throws RiceIllegalArgumentException {
472        return agendaBoService.getAgendasByType(typeId);
473    }
474
475    @Override
476    public List<AgendaDefinition> getAgendasByTypeAndContext(String typeId, String contextId)
477            throws RiceIllegalArgumentException {
478        return agendaBoService.getAgendasByTypeAndContext(typeId, contextId);
479    }
480
481    ////
482    //// agenda item methods
483    ////
484    @Override
485    public AgendaItemDefinition createAgendaItem(AgendaItemDefinition agendaItemDefinition) throws RiceIllegalArgumentException {
486        agendaItemDefinition = createUpdateAgendaItemIfNeeded(agendaItemDefinition);
487        return agendaBoService.createAgendaItem(agendaItemDefinition);
488    }
489
490    private AgendaItemDefinition createUpdateAgendaItemIfNeeded(AgendaItemDefinition agendaItemDefinition) {
491        this.crossCheckRuleId(agendaItemDefinition);
492        this.crossCheckWhenTrueId(agendaItemDefinition);
493        this.crossCheckWhenFalseId(agendaItemDefinition);
494        this.crossCheckAlwaysId(agendaItemDefinition);
495        this.crossCheckSubAgendaId(agendaItemDefinition);
496        agendaItemDefinition = createUpdateRuleIfNeeded(agendaItemDefinition);
497        agendaItemDefinition = createWhenTrueAgendaItemIfNeeded(agendaItemDefinition);
498        agendaItemDefinition = createWhenFalseAgendaItemIfNeeded(agendaItemDefinition);
499        agendaItemDefinition = createAlwaysAgendaItemIfNeeded(agendaItemDefinition);
500        return createSubAgendaIfNeeded(agendaItemDefinition);
501    }
502
503    private void crossCheckRuleId(AgendaItemDefinition agendItemDefinition)
504            throws RiceIllegalArgumentException {
505        // if both are set they better match
506        if (agendItemDefinition.getRuleId() != null && agendItemDefinition.getRule() != null) {
507            if (!agendItemDefinition.getRuleId().equals(agendItemDefinition.getRule().getId())) {
508                throw new RiceIllegalArgumentException("ruleId does not rule.getId" + agendItemDefinition.getRuleId() + " " + agendItemDefinition.getRule().getId());
509            }
510        }
511    }
512
513    private void crossCheckWhenTrueId(AgendaItemDefinition agendaItemDefinition)
514            throws RiceIllegalArgumentException {
515        // if both are set they better match
516        if (agendaItemDefinition.getWhenTrueId()!= null && agendaItemDefinition.getWhenTrue() != null) {
517            if (!agendaItemDefinition.getWhenTrueId().equals(agendaItemDefinition.getWhenTrue().getId())) {
518                throw new RiceIllegalArgumentException("when true id does not match " + agendaItemDefinition.getWhenTrueId() + " " + agendaItemDefinition.getWhenTrue().getId());
519            }
520        }
521    }
522
523    private void crossCheckWhenFalseId(AgendaItemDefinition agendItemDefinition)
524            throws RiceIllegalArgumentException {
525        // if both are set they better match
526        if (agendItemDefinition.getWhenFalseId()!= null && agendItemDefinition.getWhenFalse() != null) {
527            if (!agendItemDefinition.getWhenFalseId().equals(agendItemDefinition.getWhenFalse().getId())) {
528                throw new RiceIllegalArgumentException("when false id does not match " + agendItemDefinition.getWhenFalseId() + " " + agendItemDefinition.getWhenFalse().getId());
529            }
530        }
531    }
532
533    private void crossCheckAlwaysId(AgendaItemDefinition agendItemDefinition)
534            throws RiceIllegalArgumentException {
535        // if both are set they better match
536        if (agendItemDefinition.getAlwaysId()!= null && agendItemDefinition.getAlways() != null) {
537            if (!agendItemDefinition.getAlwaysId().equals(agendItemDefinition.getAlways().getId())) {
538                throw new RiceIllegalArgumentException("Always id does not match " + agendItemDefinition.getAlwaysId() + " " + agendItemDefinition.getAlways().getId());
539            }
540        }
541    }
542
543    private void crossCheckSubAgendaId(AgendaItemDefinition agendItemDefinition)
544            throws RiceIllegalArgumentException {
545        // if both are set they better match
546        if (agendItemDefinition.getSubAgendaId()!= null && agendItemDefinition.getSubAgenda() != null) {
547            if (!agendItemDefinition.getSubAgendaId().equals(agendItemDefinition.getSubAgenda().getId())) {
548                throw new RiceIllegalArgumentException("SubAgenda id does not match " + agendItemDefinition.getSubAgendaId() + " " + agendItemDefinition.getSubAgenda().getId());
549            }
550        }
551    }
552
553    private AgendaItemDefinition createUpdateRuleIfNeeded(AgendaItemDefinition agendaItemDefinition)
554            throws RiceIllegalArgumentException {
555        // no rule to create
556        if (agendaItemDefinition.getRule() == null) {
557            return agendaItemDefinition;
558        }
559
560        // update
561        if (agendaItemDefinition.getRule().getId() != null) {
562            this.updateRule(agendaItemDefinition.getRule());
563            RuleDefinition rule = this.getRule(agendaItemDefinition.getRule ().getId());
564            AgendaItemDefinition.Builder agendaItemBuilder = AgendaItemDefinition.Builder.create(agendaItemDefinition);
565            agendaItemBuilder.setRule(RuleDefinition.Builder.create(rule));
566            agendaItemBuilder.setRuleId(rule.getId());
567            
568            return agendaItemBuilder.build();
569        }
570
571        AgendaItemDefinition.Builder agendaItemBuilder = AgendaItemDefinition.Builder.create(agendaItemDefinition);
572        RuleDefinition ruleDefinition = this.createRule(agendaItemDefinition.getRule());
573        RuleDefinition.Builder ruleBuilder = RuleDefinition.Builder.create(ruleDefinition);
574        agendaItemBuilder.setRule(ruleBuilder);
575        agendaItemBuilder.setRuleId(ruleBuilder.getId());
576
577        return agendaItemBuilder.build();
578    }
579
580    private AgendaItemDefinition createWhenTrueAgendaItemIfNeeded(AgendaItemDefinition agendaItemDefinition) {
581        // nothing to create
582        if (agendaItemDefinition.getWhenTrue() == null) {
583            return agendaItemDefinition;
584        }
585
586        // ojb will take care of it if it has already been created
587        if (agendaItemDefinition.getWhenTrue().getId() != null) {
588            return agendaItemDefinition;
589        }
590
591        // ojb does not take care of terms and termparameters, recursively loop thru agendaitems to update terms
592        AgendaItemDefinition.Builder agendaItemBuilder = AgendaItemDefinition.Builder.create(agendaItemDefinition);
593        AgendaItemDefinition subAgendaItem = this.createUpdateAgendaItemIfNeeded(agendaItemDefinition.getWhenTrue());
594        agendaItemBuilder.setWhenTrue(AgendaItemDefinition.Builder.create(subAgendaItem));
595        agendaItemBuilder.setWhenTrueId(subAgendaItem.getId());
596
597        return agendaItemBuilder.build();
598    }
599
600
601    private AgendaItemDefinition createWhenFalseAgendaItemIfNeeded(AgendaItemDefinition agendaItemDefinition) {
602        // nothing to create
603        if (agendaItemDefinition.getWhenFalse() == null) {
604            return agendaItemDefinition;
605        }
606
607        // ojb will take care of it if it has already been created
608        if (agendaItemDefinition.getWhenFalse().getId() != null) {
609            return agendaItemDefinition;
610        }
611
612        // ojb does not take care of terms and termparameters, recursively loop thru agendaitems to update terms
613        AgendaItemDefinition.Builder agendaItemBuilder = AgendaItemDefinition.Builder.create(agendaItemDefinition);
614        AgendaItemDefinition subAgendaItem = this.createUpdateAgendaItemIfNeeded(agendaItemDefinition.getWhenFalse());
615        agendaItemBuilder.setWhenFalse(AgendaItemDefinition.Builder.create(subAgendaItem));
616        agendaItemBuilder.setWhenFalseId(subAgendaItem.getId());
617        return agendaItemBuilder.build();
618    }
619    
620
621    private AgendaItemDefinition createAlwaysAgendaItemIfNeeded(AgendaItemDefinition agendaItemDefinition) {
622        // nothing to create
623        if (agendaItemDefinition.getAlways()== null) {
624            return agendaItemDefinition;
625        } 
626        // ojb will take care of it if it has already been created
627        if (agendaItemDefinition.getAlways().getId() != null) {
628            return agendaItemDefinition;
629        }
630        
631        AgendaItemDefinition.Builder agendaItemBuilder = AgendaItemDefinition.Builder.create(agendaItemDefinition);
632        AgendaItemDefinition subAgendaItem = this.createAgendaItem(agendaItemDefinition.getAlways());
633        agendaItemBuilder.setAlways(AgendaItemDefinition.Builder.create(subAgendaItem));
634        agendaItemBuilder.setAlwaysId(subAgendaItem.getId());
635
636        return agendaItemBuilder.build();
637    }
638
639    private AgendaItemDefinition createSubAgendaIfNeeded(AgendaItemDefinition agendaItemDefinition) {
640        // nothing to create
641        if (agendaItemDefinition.getSubAgenda() == null) {
642            return agendaItemDefinition;
643        }
644
645        // ojb will take care of it if it has already been created
646        if (agendaItemDefinition.getSubAgenda().getId() != null) {
647            return agendaItemDefinition;
648        }
649
650        AgendaItemDefinition.Builder agendaItemBuilder = AgendaItemDefinition.Builder.create(agendaItemDefinition);
651        AgendaDefinition subAgenda = this.createAgenda(agendaItemDefinition.getSubAgenda());
652        agendaItemBuilder.setSubAgenda(AgendaDefinition.Builder.create(subAgenda));
653        agendaItemBuilder.setSubAgendaId(subAgenda.getId());
654
655        return agendaItemBuilder.build();
656    }
657
658    @Override
659    public AgendaItemDefinition getAgendaItem(String id) throws RiceIllegalArgumentException {
660        AgendaItemDefinition agendaItem = agendaBoService.getAgendaItemById(id);
661
662        if (agendaItem != null) {
663            return setTermValuesForAgendaItem(agendaItem).build();
664        }
665
666        return agendaItem;
667    }
668
669    private AgendaItemDefinition.Builder setTermValuesForAgendaItem(AgendaItemDefinition agendaItem) {
670        if (agendaItem == null){
671            return null;
672        }
673
674        AgendaItemDefinition.Builder itemBuiler = AgendaItemDefinition.Builder.create(agendaItem);
675        if (itemBuiler.getRule() != null) {
676            // Set the termValues on the agenda item.
677            PropositionDefinition proposition = agendaItem.getRule().getProposition();
678            if (proposition != null) {
679                proposition = this.orderCompoundPropositionsIfNeeded(proposition);
680                itemBuiler.getRule().setProposition(this.replaceTermValues(proposition));
681            }
682        }
683
684        // Recursively set the term values on child agenda items.
685        itemBuiler.setWhenTrue(setTermValuesForAgendaItem(agendaItem.getWhenTrue()));
686        itemBuiler.setWhenFalse(setTermValuesForAgendaItem(agendaItem.getWhenFalse()));
687        itemBuiler.setAlways(setTermValuesForAgendaItem(agendaItem.getAlways()));
688
689        return itemBuiler;
690    }
691
692    @Override
693    public List<AgendaItemDefinition> getAgendaItemsByType(String typeId)
694            throws RiceIllegalArgumentException {
695        return agendaBoService.getAgendaItemsByType(typeId);
696    }
697
698    @Override
699    public List<AgendaItemDefinition> getAgendaItemsByContext(String contextId) throws RiceIllegalArgumentException {
700        return agendaBoService.getAgendaItemsByContext(contextId);
701    }
702
703    @Override
704    public List<AgendaItemDefinition> getAgendaItemsByTypeAndContext(String typeId, String contextId)
705            throws RiceIllegalArgumentException {
706        return agendaBoService.getAgendaItemsByTypeAndContext(typeId, contextId);
707    }
708
709    @Override
710    public void deleteAgendaItem(String id) throws RiceIllegalArgumentException {
711        agendaBoService.deleteAgendaItem(id);
712    }
713
714    @Override
715    public void updateAgendaItem(AgendaItemDefinition agendaItemDefinition) throws RiceIllegalArgumentException {
716        agendaItemDefinition = createUpdateAgendaItemIfNeeded(agendaItemDefinition);
717        agendaBoService.updateAgendaItem(agendaItemDefinition);
718    }
719
720    private void crossCheckPropId(RuleDefinition ruleDefinition)
721            throws RiceIllegalArgumentException {
722        // if both are set they better match
723        if (ruleDefinition.getPropId() != null && ruleDefinition.getProposition() != null) {
724            if (!ruleDefinition.getPropId().equals(ruleDefinition.getProposition().getId())) {
725                throw new RiceIllegalArgumentException("propId does not match proposition.getId" + ruleDefinition.getPropId() + " " + ruleDefinition.getProposition().getId());
726            }
727        }
728    }
729
730    ////
731    //// rule methods
732    ////
733    @Override
734    public RuleDefinition getRuleByNameAndNamespace(String name, String namespace) {
735        return this.ruleBoService.getRuleByNameAndNamespace(name, namespace);
736    }
737
738
739    @Override
740    public RuleDefinition createRule(RuleDefinition ruleDefinition) throws RiceIllegalArgumentException {
741        if (ruleDefinition.getId() != null) {
742            RuleDefinition orig = this.getRule(ruleDefinition.getId());
743
744            if (orig != null) {
745                throw new RiceIllegalArgumentException(ruleDefinition.getId());
746            }
747        } else {
748            // if no id then set it because it is needed to store propositions connected to this rule
749            String ruleId = getSequenceAccessorService().getNextAvailableSequenceNumber("KRMS_RULE_S", RuleBo.class).toString();
750            RuleDefinition.Builder ruleBldr = RuleDefinition.Builder.create(ruleDefinition);
751            ruleBldr.setId(ruleId);
752            ruleDefinition = ruleBldr.build();
753        }
754
755        // if both are set they better match
756        crossCheckPropId(ruleDefinition);
757        ruleDefinition = this.createUpdatePropositionIfNeeded(ruleDefinition);
758        ruleDefinition = ruleBoService.createRule(ruleDefinition);
759
760        return ruleDefinition;
761    }
762
763    private RuleDefinition createRuleIfNeeded(RuleDefinition ruleDefinition) throws RiceIllegalArgumentException {
764
765        // no rule to create
766        if (ruleDefinition == null) {
767            return null;
768        }
769
770        // if no id then set it because it is needed to store propositions connected to this rule
771        if (ruleDefinition.getId() == null) {
772            String ruleId = getSequenceAccessorService().getNextAvailableSequenceNumber("KRMS_RULE_S", RuleBo.class).toString();
773            RuleDefinition.Builder ruleBldr = RuleDefinition.Builder.create(ruleDefinition);
774            ruleBldr.setId(ruleId);
775            ruleDefinition = ruleBldr.build();
776        }
777
778        // if both are set they better match
779        crossCheckPropId(ruleDefinition);
780        ruleDefinition = this.createUpdatePropositionIfNeeded(ruleDefinition);
781
782        return ruleDefinition;
783    }
784
785    private RuleDefinition createUpdatePropositionIfNeeded(RuleDefinition rule) {
786        // no prop to create
787        if (rule.getProposition() == null) {
788            return rule;
789        }
790
791        // update 
792        if (rule.getProposition().getId() != null) {
793            this.updateProposition(rule.getProposition());
794            PropositionDefinition prop = this.getProposition(rule.getProposition().getId());
795            RuleDefinition.Builder ruleBldr = RuleDefinition.Builder.create(rule);
796            ruleBldr.setProposition(PropositionDefinition.Builder.create(prop));
797            ruleBldr.setPropId(prop.getId());
798            return ruleBldr.build();
799        }
800
801        // create the proposition
802        RuleDefinition.Builder ruleBldr = RuleDefinition.Builder.create(rule);
803        PropositionDefinition propositionDefinition = null;
804        // ojb will take care of props that have already been created, but we still need to take care of the terms.
805        PropositionDefinition.Builder propBldr = ruleBldr.getProposition();
806
807        if (rule.getProposition().getId() != null) {
808            this.crossCheckPropositionParameters(rule.getProposition());
809            propBldr = setSequenceOnCompoundPropositionsIfNeeded(propBldr);
810            propBldr = maintainTermValuesAndChildPropositions(propBldr);
811        } else {
812            // create the proposition
813            propBldr.setRule(ruleBldr);
814            propositionDefinition = this.createProposition(propBldr.build());
815            propBldr = PropositionDefinition.Builder.create(propositionDefinition);
816        }
817
818        // now update the rule so it holds the proposition id
819        ruleBldr.setProposition(propBldr);
820
821        return ruleBldr.build();
822    }
823
824    @Override
825    public void updateRule(RuleDefinition ruleDefinition) throws RiceIllegalArgumentException {
826        crossCheckPropId(ruleDefinition);
827        ruleDefinition = this.createUpdatePropositionIfNeeded(ruleDefinition);
828
829        ruleBoService.updateRule(ruleDefinition);
830    }
831
832    @Override
833    public void deleteRule(String id) throws RiceIllegalArgumentException {
834        ruleBoService.deleteRule(id);
835    }
836
837    ////
838    //// action methods
839    ////
840    @Override
841    public ActionDefinition createAction(ActionDefinition actionDefinition) throws RiceIllegalArgumentException {
842        return actionBoService.createAction(actionDefinition);
843    }
844
845    @Override
846    public void updateAction(ActionDefinition actionDefinition) throws RiceIllegalArgumentException {
847        actionBoService.updateAction(actionDefinition);
848    }
849
850    @Override
851    public void deleteAction(String id) throws RiceIllegalArgumentException {
852        throw new RiceIllegalArgumentException("not implemented yet because not supported by the bo service");
853//        actionBoService.deleteAction(id);
854    }
855
856    @Override
857    public ActionDefinition getAction(String actionId) {
858        return actionBoService.getActionByActionId(actionId);
859    }
860
861    @Override
862    public List<ActionDefinition> getActions(List<String> actionIds) {
863        // TODO: implement this more efficiently by adding the bulk op to the bo service and calling it
864        List<ActionDefinition> list = new ArrayList<ActionDefinition>();
865
866        for (String id : actionIds) {
867            list.add(this.getAction(id));
868        }
869
870        return list;
871    }
872
873    private void crossCheckPropositionParameters(PropositionDefinition propositionDefinition) {
874        // check that if the value and termValue are both supplied that they match
875        for (PropositionParameter param : propositionDefinition.getParameters()) {
876            if (param.getValue() != null && param.getTermValue() != null) {
877                if (!param.getValue().equals(param.getTermValue().getId())) {
878                    throw new RiceIllegalArgumentException("value does not match termValue.id on param "
879                            + param.getSequenceNumber() + " " + param.getValue() + " " + param.getTermValue().getId());
880                }
881            }
882        }
883    }
884
885
886    ////
887    //// proposition methods
888    ////
889    @Override
890    public PropositionDefinition createProposition(PropositionDefinition propositionDefinition) throws RiceIllegalArgumentException {
891        // CREATE
892        if (propositionDefinition.getId() != null) {
893            PropositionDefinition orig = this.getProposition(propositionDefinition.getId());
894            if (orig != null) {
895                throw new RiceIllegalArgumentException(propositionDefinition.getId());
896            }
897        }
898
899        crossCheckPropositionParameters(propositionDefinition);
900        PropositionDefinition.Builder propBldr = PropositionDefinition.Builder.create(propositionDefinition);
901        propBldr = setSequenceOnCompoundPropositionsIfNeeded(propBldr);
902        propBldr = maintainTermValuesAndChildPropositions(propBldr);
903        PropositionDefinition prop = propositionBoService.createProposition(propBldr.build());
904
905        return prop;
906    }
907
908    private PropositionDefinition.Builder maintainTermValuesAndChildPropositions(PropositionDefinition.Builder propBldr) {
909        if (PropositionType.SIMPLE.getCode().equalsIgnoreCase(propBldr.getPropositionTypeCode())) {
910            return maintainTermValues(propBldr);
911        } else {
912            return createChildPropsIfNeeded(propBldr);
913        }
914    }
915
916    private PropositionDefinition.Builder maintainTermValues(PropositionDefinition.Builder propBldr) {
917        if (propBldr.getParameters() == null) {
918            return propBldr;
919        }
920
921        if (propBldr.getParameters().isEmpty()) {
922            return propBldr;
923        }
924
925        boolean updated = false;
926        List<PropositionParameter.Builder> paramBldrs = new ArrayList<PropositionParameter.Builder> ();
927
928        for (PropositionParameter.Builder paramBldr : propBldr.getParameters()) {
929            paramBldrs.add(paramBldr);
930
931            // link the param the proposition's id
932            // not sure we need to do this but...
933            if (paramBldr.getPropId() == null) {
934                paramBldr.setPropId(propBldr.getId());
935                updated = true;
936            }
937
938            // create the termvalue if it was specified
939            if (paramBldr.getTermValue() != null) {
940                TermDefinition termValue = paramBldr.getTermValue();
941
942                // no id means it does not exist yet
943                if (termValue.getId() == null) {
944                    termValue = this.termRepositoryService.createTerm(termValue);
945                    paramBldr.setTermValue(termValue);
946                    updated = true;
947                } else {
948                    this.termRepositoryService.updateTerm(termValue);
949                }
950                
951                if ((paramBldr.getValue() == null) || (!paramBldr.getValue().equals(termValue.getId()))) {
952                    paramBldr.setValue(termValue.getId());
953                    updated = true;
954                }
955            }
956        }
957
958        if (!updated) {
959            return propBldr;
960        }
961
962        propBldr.setParameters(paramBldrs);
963        return propBldr;
964    }
965
966    private PropositionDefinition.Builder createChildPropsIfNeeded(PropositionDefinition.Builder propBldr) {
967        if (propBldr.getCompoundComponents() == null) {
968            return propBldr;
969        }
970
971        if (propBldr.getCompoundComponents().isEmpty()) {
972            return propBldr;
973        }
974
975        List<PropositionDefinition.Builder> childPropBldrs = new ArrayList<PropositionDefinition.Builder>();
976
977        for (PropositionDefinition.Builder compPropBldr : propBldr.getCompoundComponents()) {
978            compPropBldr.setRuleId(propBldr.getRuleId());
979            propBldr = setSequenceOnCompoundPropositionsIfNeeded(propBldr);
980            compPropBldr = maintainTermValuesAndChildPropositions(compPropBldr);
981            childPropBldrs.add(compPropBldr);
982        }
983
984        propBldr.setCompoundComponents(childPropBldrs);
985
986        return propBldr;
987    }
988
989    @Override
990    public PropositionDefinition getProposition(String id) throws RiceIllegalArgumentException {
991        if (StringUtils.isBlank(id)) {
992            throw new RiceIllegalArgumentException("Proposition id must not be null or blank");
993        }
994
995        PropositionDefinition proposition = propositionBoService.getPropositionById(id);
996
997        if (proposition == null) {
998            return null;
999        }
1000
1001        proposition = this.replaceTermValues(proposition).build();
1002        proposition = this.orderCompoundPropositionsIfNeeded(proposition);
1003
1004        return proposition;
1005    }
1006
1007    private PropositionDefinition orderCompoundPropositionsIfNeeded(PropositionDefinition prop) {
1008        if (!prop.getPropositionTypeCode().equals(PropositionType.COMPOUND.getCode())) {
1009            return prop;
1010        }
1011
1012        if (prop.getCompoundComponents() == null) {
1013            return prop;
1014        }
1015
1016        if (prop.getCompoundComponents().size() <= 1) {
1017            return prop;
1018        }
1019
1020        PropositionDefinition.Builder propBldr = PropositionDefinition.Builder.create(prop);        
1021        List<PropositionDefinition> childProps = new ArrayList<PropositionDefinition> (prop.getCompoundComponents());
1022        Collections.sort(childProps, new CompoundPropositionComparator());
1023        List<PropositionDefinition.Builder> childPropBldrs = new ArrayList<PropositionDefinition.Builder> (childProps.size());
1024
1025        for (PropositionDefinition chidProp : childProps) {
1026            PropositionDefinition.Builder childPropBlder = PropositionDefinition.Builder.create(chidProp);
1027            childPropBldrs.add(childPropBlder);
1028        }
1029
1030        propBldr.setCompoundComponents(childPropBldrs);
1031
1032        return propBldr.build();
1033    }
1034
1035    private PropositionDefinition.Builder replaceTermValues(PropositionDefinition proposition) {
1036
1037        PropositionDefinition.Builder bldr = PropositionDefinition.Builder.create(proposition);
1038
1039        // recursively add termValues to child propositions.
1040        if (!PropositionType.SIMPLE.getCode().equalsIgnoreCase(proposition.getPropositionTypeCode())) {
1041            List<PropositionDefinition.Builder> cmpdProps = new ArrayList<PropositionDefinition.Builder>();
1042            for (PropositionDefinition cmpdProp : proposition.getCompoundComponents()) {
1043                cmpdProps.add(replaceTermValues(cmpdProp));
1044            }
1045            bldr.setCompoundComponents(cmpdProps);
1046            return bldr;
1047        }
1048
1049        // that have parameters
1050        if (proposition.getParameters() == null) {
1051            return bldr;
1052        }
1053
1054        if (proposition.getParameters().isEmpty()) {
1055            return bldr;
1056        }
1057
1058        boolean found = false;
1059        List<PropositionParameter.Builder> params = new ArrayList<PropositionParameter.Builder>(proposition.getParameters().size());
1060
1061        for (PropositionParameter param : proposition.getParameters()) {
1062            if (!PropositionParameterType.TERM.getCode().equalsIgnoreCase(param.getParameterType())) {
1063                params.add(PropositionParameter.Builder.create(param));
1064                continue;
1065            }
1066
1067            // inflate the termValue
1068            found = true;
1069            TermDefinition termValue = this.termRepositoryService.getTerm(param.getValue());
1070            PropositionParameter.Builder parmbldr = PropositionParameter.Builder.create(param);
1071            parmbldr.setTermValue(termValue);
1072            params.add(parmbldr);
1073        }
1074
1075        if (!found) {
1076            return bldr;
1077        }
1078
1079        bldr.setParameters(params);
1080
1081        return bldr;
1082    }
1083
1084
1085    private Set<PropositionDefinition> replaceTermValuesInSet(Set<PropositionDefinition> propositions) {
1086        if (propositions == null) {
1087            return null;
1088        }
1089
1090        if (propositions.isEmpty()) {
1091            return propositions;
1092        }
1093
1094        Set<PropositionDefinition> set = new LinkedHashSet<PropositionDefinition>(propositions.size());
1095        for (PropositionDefinition proposition : propositions) {
1096            proposition = this.replaceTermValues(proposition).build();
1097            set.add(proposition);
1098        }
1099
1100        return set;
1101    }
1102
1103    @Override
1104    public Set<PropositionDefinition> getPropositionsByType(String typeId) throws RiceIllegalArgumentException {
1105        return replaceTermValuesInSet(propositionBoService.getPropositionsByType(typeId));
1106    }
1107
1108    @Override
1109    public Set<PropositionDefinition> getPropositionsByRule(String ruleId) throws RiceIllegalArgumentException {
1110        return replaceTermValuesInSet(propositionBoService.getPropositionsByRule(ruleId));
1111    }
1112
1113    @Override
1114    public void updateProposition(PropositionDefinition propositionDefinition) throws RiceIllegalArgumentException {
1115        this.crossCheckPropositionParameters(propositionDefinition);
1116        PropositionDefinition.Builder propBldr = PropositionDefinition.Builder.create(propositionDefinition);
1117        propBldr = setSequenceOnCompoundPropositionsIfNeeded(propBldr);
1118        propBldr = maintainTermValuesAndChildPropositions(propBldr);
1119
1120        propositionBoService.updateProposition(propBldr.build());
1121    }
1122
1123    private PropositionDefinition.Builder setSequenceOnCompoundPropositionsIfNeeded(PropositionDefinition.Builder propBldr) {
1124        if (propBldr.getCompoundComponents() == null) {
1125            return propBldr;
1126        }
1127
1128        if (propBldr.getCompoundComponents().size() <= 1) {
1129            return propBldr;
1130        }
1131
1132        List<PropositionDefinition.Builder> childList = new ArrayList<PropositionDefinition.Builder>(propBldr.getCompoundComponents().size());
1133        int i = 1; // start at 1 because rice does that
1134
1135        for (PropositionDefinition.Builder childPropBldr : propBldr.getCompoundComponents()) {
1136            childPropBldr.setCompoundSequenceNumber(i);
1137            i++;
1138            childList.add(childPropBldr);
1139        }
1140        propBldr.setCompoundComponents(childList);
1141        return propBldr;
1142    }
1143
1144    @Override
1145    public void deleteProposition(String id) throws RiceIllegalArgumentException {
1146        propositionBoService.deleteProposition(id);
1147    }
1148
1149    ////
1150    //// natural language usage methods
1151    ////
1152    @Override
1153    public NaturalLanguageUsage createNaturalLanguageUsage(NaturalLanguageUsage naturalLanguageUsage) throws RiceIllegalArgumentException {
1154        return naturalLanguageUsageBoService.createNaturalLanguageUsage(naturalLanguageUsage);
1155    }
1156
1157    @Override
1158    public NaturalLanguageUsage getNaturalLanguageUsage(String id) throws RiceIllegalArgumentException {
1159        return naturalLanguageUsageBoService.getNaturalLanguageUsage(id);
1160    }
1161
1162    @Override
1163    public void updateNaturalLanguageUsage(NaturalLanguageUsage naturalLanguageUsage) throws RiceIllegalArgumentException {
1164        naturalLanguageUsageBoService.updateNaturalLanguageUsage(naturalLanguageUsage);
1165    }
1166
1167    @Override
1168    public void deleteNaturalLanguageUsage(String naturalLanguageUsageId) throws RiceIllegalArgumentException {
1169        naturalLanguageUsageBoService.deleteNaturalLanguageUsage(naturalLanguageUsageId);
1170    }
1171
1172    @Override
1173    public List<NaturalLanguageUsage> getNaturalLanguageUsagesByNamespace(String namespace)
1174            throws RiceIllegalArgumentException {
1175        return this.naturalLanguageUsageBoService.findNaturalLanguageUsagesByNamespace(namespace);
1176    }
1177
1178    @Override
1179    public NaturalLanguageUsage getNaturalLanguageUsageByNameAndNamespace(String name, String namespace)
1180            throws RiceIllegalArgumentException {
1181        return this.naturalLanguageUsageBoService.getNaturalLanguageUsageByName(namespace, name);
1182    }
1183
1184
1185    ////
1186    //// natural language translations
1187    ////
1188    @Override
1189    public String translateNaturalLanguageForObject(String naturalLanguageUsageId,
1190                                                    String typeId,
1191                                                    String krmsObjectId,
1192                                                    String languageCode)
1193            throws RiceIllegalArgumentException {
1194
1195        return this.getTranslateBusinessMethods().translateNaturalLanguageForObject(naturalLanguageUsageId, typeId, krmsObjectId, languageCode);
1196    }
1197
1198    @Override
1199    public String translateNaturalLanguageForProposition(String naturalLanguageUsageId,
1200                                                         PropositionDefinition proposition, String languageCode)
1201            throws RiceIllegalArgumentException {
1202
1203        return this.getTranslateBusinessMethods().translateNaturalLanguageForProposition(naturalLanguageUsageId, proposition, languageCode);
1204    }
1205
1206    @Override
1207    public NaturalLanguageTree translateNaturalLanguageTreeForProposition(String naturalLanguageUsageId, 
1208            PropositionDefinition propositionDefinintion, String languageCode) throws RiceIllegalArgumentException {
1209
1210        return getTranslateBusinessMethods().translateNaturalLanguageTreeForProposition(naturalLanguageUsageId,
1211                propositionDefinintion, languageCode);
1212    }
1213
1214    ////
1215    //// context methods
1216    ////
1217    @Override
1218    public ContextDefinition createContext(ContextDefinition contextDefinition) throws RiceIllegalArgumentException {
1219        return this.contextBoService.createContext(contextDefinition);
1220    }
1221
1222
1223    @Override
1224    public ContextDefinition findCreateContext(ContextDefinition contextDefinition) throws RiceIllegalArgumentException {
1225        ContextDefinition orig = this.contextBoService.getContextByNameAndNamespace(contextDefinition.getName(), contextDefinition.getNamespace());
1226
1227        if (orig != null) {
1228            return orig;
1229        }
1230
1231        return this.contextBoService.createContext(contextDefinition);
1232    }
1233
1234    @Override
1235    public void updateContext(ContextDefinition contextDefinition) throws RiceIllegalArgumentException {
1236        this.contextBoService.updateContext(contextDefinition);
1237    }
1238
1239    @Override
1240    public void deleteContext(String id) throws RiceIllegalArgumentException {
1241        throw new RiceIllegalArgumentException("not implemented yet");
1242    }
1243
1244    @Override
1245    public ContextDefinition getContext(String id) throws RiceIllegalArgumentException {
1246        return this.contextBoService.getContextByContextId(id);
1247    }
1248
1249    @Override
1250    public ContextDefinition getContextByNameAndNamespace(String name, String namespace) throws RiceIllegalArgumentException {
1251        return this.contextBoService.getContextByNameAndNamespace(name, namespace);
1252    }
1253
1254    ////
1255    //// natural language templates
1256    ////
1257    @Override
1258    public NaturalLanguageTemplate createNaturalLanguageTemplate(NaturalLanguageTemplate naturalLanguageTemplate) throws RiceIllegalArgumentException {
1259        return this.naturalLanguageTemplateBoService.createNaturalLanguageTemplate(naturalLanguageTemplate);
1260    }
1261
1262    @Override
1263    public NaturalLanguageTemplate getNaturalLanguageTemplate(String naturalLanguageTemplateId) throws RiceIllegalArgumentException {
1264        return this.naturalLanguageTemplateBoService.getNaturalLanguageTemplate(naturalLanguageTemplateId);
1265    }
1266
1267    @Override
1268    public void updateNaturalLanguageTemplate(NaturalLanguageTemplate naturalLanguageTemplate) throws RiceIllegalArgumentException {
1269        this.naturalLanguageTemplateBoService.updateNaturalLanguageTemplate(naturalLanguageTemplate);
1270    }
1271
1272    @Override
1273    public void deleteNaturalLanguageTemplate(String naturalLanguageTemplateId) throws RiceIllegalArgumentException {
1274        this.naturalLanguageTemplateBoService.deleteNaturalLanguageTemplate(naturalLanguageTemplateId);
1275    }
1276
1277    @Override
1278    public List<NaturalLanguageTemplate> findNaturalLanguageTemplatesByLanguageCode(String languageCode) throws RiceIllegalArgumentException {
1279        return this.naturalLanguageTemplateBoService.findNaturalLanguageTemplatesByLanguageCode(languageCode);
1280    }
1281
1282    @Override
1283    public NaturalLanguageTemplate findNaturalLanguageTemplateByLanguageCodeTypeIdAndNluId(String languageCode, String typeId, String naturalLanguageUsageId) throws RiceIllegalArgumentException {
1284        return this.naturalLanguageTemplateBoService.findNaturalLanguageTemplateByLanguageCodeTypeIdAndNluId(languageCode, typeId, naturalLanguageUsageId);
1285    }
1286
1287    @Override
1288    public List<NaturalLanguageTemplate> findNaturalLanguageTemplatesByNaturalLanguageUsage(String naturalLanguageUsageId) throws RiceIllegalArgumentException {
1289        return this.naturalLanguageTemplateBoService.findNaturalLanguageTemplatesByNaturalLanguageUsage(naturalLanguageUsageId);
1290    }
1291
1292    @Override
1293    public List<NaturalLanguageTemplate> findNaturalLanguageTemplatesByType(String typeId) throws RiceIllegalArgumentException {
1294        return this.naturalLanguageTemplateBoService.findNaturalLanguageTemplatesByType(typeId);
1295    }
1296
1297    @Override
1298    public List<NaturalLanguageTemplate> findNaturalLanguageTemplatesByTemplate(String template) throws RiceIllegalArgumentException {
1299        return this.naturalLanguageTemplateBoService.findNaturalLanguageTemplatesByTemplate(template);
1300    }
1301
1302    @Override
1303    public List<String> findContextIds(QueryByCriteria queryByCriteria) throws RiceIllegalArgumentException {
1304        GenericQueryResults<ContextBo> results = getCriteriaLookupService().lookup(ContextBo.class, queryByCriteria);
1305
1306        List<String> list = new ArrayList<String> ();
1307        for (ContextBo bo : results.getResults()) {
1308            list.add(bo.getId());
1309        }
1310
1311        return list;
1312    }
1313
1314    @Override
1315    public List<String> findAgendaIds(QueryByCriteria queryByCriteria) throws RiceIllegalArgumentException {
1316        GenericQueryResults<AgendaBo> results = getCriteriaLookupService().lookup(AgendaBo.class, queryByCriteria);
1317        List<String> list = new ArrayList<String> ();
1318
1319        for (AgendaBo bo : results.getResults()) {
1320            list.add(bo.getId());
1321        }
1322
1323        return list;
1324    }
1325
1326    @Override
1327    public List<String> findRuleIds(QueryByCriteria queryByCriteria) throws RiceIllegalArgumentException {
1328        GenericQueryResults<RuleBo> results = getCriteriaLookupService().lookup(RuleBo.class, queryByCriteria);
1329        List<String> list = new ArrayList<String> ();
1330
1331        for (RuleBo bo : results.getResults()) {
1332            list.add(bo.getId());
1333        }
1334
1335        return list;
1336    }
1337
1338    @Override
1339    public List<String> findPropositionIds(QueryByCriteria queryByCriteria) throws RiceIllegalArgumentException {
1340        GenericQueryResults<PropositionBo> results = getCriteriaLookupService().lookup(PropositionBo.class, queryByCriteria);
1341
1342        List<String> list = new ArrayList<String> ();
1343        for (PropositionBo bo : results.getResults()) {
1344            list.add(bo.getId());
1345        }
1346
1347        return list;
1348    }
1349
1350    @Override
1351    public List<String> findActionIds(QueryByCriteria queryByCriteria) throws RiceIllegalArgumentException {
1352        GenericQueryResults<ActionBo> results = getCriteriaLookupService().lookup(ActionBo.class, queryByCriteria);
1353
1354        List<String> list = new ArrayList<String> ();
1355        for (ActionBo bo : results.getResults()) {
1356            list.add(bo.getId());
1357        }
1358
1359        return list;
1360    }
1361    
1362    /**
1363     * Sets the businessObjectService property.
1364     *
1365     * @param businessObjectService The businessObjectService to set.
1366     */
1367    @Override
1368    public void setBusinessObjectService(final BusinessObjectService businessObjectService) {
1369        super.setBusinessObjectService(businessObjectService);
1370        if (referenceObjectBindingBoService instanceof ReferenceObjectBindingBoServiceImpl) {
1371            ((ReferenceObjectBindingBoServiceImpl) referenceObjectBindingBoService).setBusinessObjectService(businessObjectService);
1372        }
1373
1374        if (agendaBoService instanceof AgendaBoServiceImpl) {
1375            ((AgendaBoServiceImpl) agendaBoService).setBusinessObjectService(businessObjectService);
1376        }
1377
1378        if (ruleBoService instanceof RuleBoServiceImpl) {
1379            ((RuleBoServiceImpl) ruleBoService).setBusinessObjectService(businessObjectService);
1380        }
1381
1382        if (actionBoService instanceof ActionBoServiceImpl) {
1383            ((ActionBoServiceImpl) actionBoService).setBusinessObjectService(businessObjectService);
1384        }
1385
1386        if (propositionBoService instanceof PropositionBoServiceImpl) {
1387            ((PropositionBoServiceImpl) propositionBoService).setBusinessObjectService(businessObjectService);
1388        }
1389
1390        if (naturalLanguageUsageBoService instanceof NaturalLanguageUsageBoServiceImpl) {
1391            ((NaturalLanguageUsageBoServiceImpl) naturalLanguageUsageBoService).setBusinessObjectService(businessObjectService);
1392        }
1393
1394        if (naturalLanguageTemplateBoService instanceof NaturalLanguageTemplateBoServiceImpl) {
1395            ((NaturalLanguageTemplateBoServiceImpl) naturalLanguageTemplateBoService).setBusinessObjectService(businessObjectService);
1396        }
1397
1398        if (contextBoService instanceof ContextBoServiceImpl) {
1399            ((ContextBoServiceImpl) contextBoService).setBusinessObjectService(businessObjectService);
1400        }
1401
1402        if (termRepositoryService instanceof TermBoServiceImpl) {
1403            ((TermBoServiceImpl) termRepositoryService).setBusinessObjectService(businessObjectService);
1404        }
1405    }
1406}