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