001/**
002 * Copyright 2005-2013 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.krms.impl.repository;
017
018import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
019import org.kuali.rice.krms.api.repository.RuleManagementService;
020import org.kuali.rice.krms.api.repository.NaturalLanguage;
021import org.kuali.rice.krms.api.repository.TranslateBusinessMethods;
022import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition;
023import org.kuali.rice.krms.api.repository.agenda.AgendaItemDefinition;
024import org.kuali.rice.krms.api.repository.language.NaturalLanguageTemplaterContract;
025import org.kuali.rice.krms.api.repository.reference.ReferenceObjectBinding;
026import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
027import org.kuali.rice.krms.impl.repository.language.SimpleNaturalLanguageTemplater;
028
029import java.util.ArrayList;
030import java.util.List;
031import java.util.Map;
032
033import static org.kuali.rice.core.api.criteria.PredicateFactory.in;
034
035/**
036 * The implementation of {@link org.kuali.rice.krms.api.repository.RuleManagementService} operations facilitate management of rules and
037 * associated information.
038 *
039 * @author Kuali Rice Team (rice.collab@kuali.org)
040 */
041public class KSRuleManagementServiceImpl extends RuleManagementServiceImpl implements RuleManagementService {
042
043    private TranslateBusinessMethods translationBusinessMethods;
044    private NaturalLanguageTemplaterContract templater = new SimpleNaturalLanguageTemplater();
045    private AgendaBoService agendaBoService = new AgendaBoServiceImpl();
046
047    @Override
048    public List<ReferenceObjectBinding> findReferenceObjectBindingsByReferenceObjectIds(String referenceObjectReferenceDiscriminatorType,
049                                                                                        List<String> referenceObjectIds)
050            throws RiceIllegalArgumentException {
051        if (referenceObjectReferenceDiscriminatorType == null) {
052            throw new RiceIllegalArgumentException("reference binding object discriminator type must not be null");
053        }
054
055        if (referenceObjectIds == null) {
056            throw new RiceIllegalArgumentException("reference object ids must not be null");
057        }
058
059        List<ReferenceObjectBinding> list = new ArrayList<ReferenceObjectBinding>();
060        for(String referenceObjectId : referenceObjectIds){
061            for (ReferenceObjectBinding binding : this.getReferenceObjectBindingBoService().findReferenceObjectBindingsByReferenceObject(referenceObjectId)) {
062                if (binding.getReferenceDiscriminatorType().equals(referenceObjectReferenceDiscriminatorType)) {
063                    list.add(binding);
064                }
065            }
066        }
067
068        return list;
069    }
070
071    @Override
072    public List<NaturalLanguage> translateNaturalLanguageForObjects(String naturalLanguageUsageId, String typeId, List<String> krmsObjectIds,
073                                                                    String languageCode)
074            throws RiceIllegalArgumentException {
075
076        List<NaturalLanguage> nlList = new ArrayList<NaturalLanguage>();
077        for(String krmsObjectId : krmsObjectIds){
078            String nl = this.getTranslateBusinessMethods().translateNaturalLanguageForObject(naturalLanguageUsageId, typeId, krmsObjectId, languageCode);
079
080            NaturalLanguage.Builder nlBuilder = NaturalLanguage.Builder.create();
081            nlBuilder.setKrmsObjectId(krmsObjectId);
082            nlBuilder.setNaturalLanguage(nl);
083            nlList.add(nlBuilder.build());
084        }
085
086        return nlList;
087    }
088
089    ////
090    //// agenda item methods
091    ////
092    @Override
093    public AgendaItemDefinition createAgendaItem(AgendaItemDefinition agendaItemDefinition) throws RiceIllegalArgumentException {
094        return createUpdateAgendaItemIfNeeded(agendaItemDefinition);
095    }
096
097    @Override
098    public void updateAgendaItem(AgendaItemDefinition agendaItemDefinition) throws RiceIllegalArgumentException {
099        createUpdateAgendaItemIfNeeded(agendaItemDefinition);
100    }
101
102    private AgendaItemDefinition createUpdateAgendaItemIfNeeded(AgendaItemDefinition agendaItemDefinition) {
103        this.crossCheckRuleId(agendaItemDefinition);
104        this.crossCheckWhenTrueId(agendaItemDefinition);
105        this.crossCheckWhenFalseId(agendaItemDefinition);
106        this.crossCheckAlwaysId(agendaItemDefinition);
107        this.crossCheckSubAgendaId(agendaItemDefinition);
108        agendaItemDefinition = createUpdateRuleIfNeeded(agendaItemDefinition);
109        agendaItemDefinition = createWhenTrueAgendaItemIfNeeded(agendaItemDefinition);
110        agendaItemDefinition = createWhenFalseAgendaItemIfNeeded(agendaItemDefinition);
111        agendaItemDefinition = createAlwaysAgendaItemIfNeeded(agendaItemDefinition);
112        agendaItemDefinition = createSubAgendaIfNeeded(agendaItemDefinition);
113
114        // Create or update
115        if (agendaItemDefinition.getId() != null) {
116            agendaBoService.updateAgendaItem(agendaItemDefinition);
117        } else {
118            agendaItemDefinition = agendaBoService.createAgendaItem(agendaItemDefinition);
119        }
120
121        return agendaItemDefinition;
122    }
123
124    private void crossCheckRuleId(AgendaItemDefinition agendItemDefinition)
125            throws RiceIllegalArgumentException {
126        // if both are set they better match
127        if (agendItemDefinition.getRuleId() != null && agendItemDefinition.getRule() != null) {
128            if (!agendItemDefinition.getRuleId().equals(agendItemDefinition.getRule().getId())) {
129                throw new RiceIllegalArgumentException("ruleId does not rule.getId" + agendItemDefinition.getRuleId() + " " + agendItemDefinition.getRule().getId());
130            }
131        }
132    }
133
134    private void crossCheckWhenTrueId(AgendaItemDefinition agendaItemDefinition)
135            throws RiceIllegalArgumentException {
136        // if both are set they better match
137        if (agendaItemDefinition.getWhenTrueId()!= null && agendaItemDefinition.getWhenTrue() != null) {
138            if (!agendaItemDefinition.getWhenTrueId().equals(agendaItemDefinition.getWhenTrue().getId())) {
139                throw new RiceIllegalArgumentException("when true id does not match " + agendaItemDefinition.getWhenTrueId() + " " + agendaItemDefinition.getWhenTrue().getId());
140            }
141        }
142    }
143
144    private void crossCheckWhenFalseId(AgendaItemDefinition agendItemDefinition)
145            throws RiceIllegalArgumentException {
146        // if both are set they better match
147        if (agendItemDefinition.getWhenFalseId()!= null && agendItemDefinition.getWhenFalse() != null) {
148            if (!agendItemDefinition.getWhenFalseId().equals(agendItemDefinition.getWhenFalse().getId())) {
149                throw new RiceIllegalArgumentException("when false id does not match " + agendItemDefinition.getWhenFalseId() + " " + agendItemDefinition.getWhenFalse().getId());
150            }
151        }
152    }
153
154    private void crossCheckAlwaysId(AgendaItemDefinition agendItemDefinition)
155            throws RiceIllegalArgumentException {
156        // if both are set they better match
157        if (agendItemDefinition.getAlwaysId()!= null && agendItemDefinition.getAlways() != null) {
158            if (!agendItemDefinition.getAlwaysId().equals(agendItemDefinition.getAlways().getId())) {
159                throw new RiceIllegalArgumentException("Always id does not match " + agendItemDefinition.getAlwaysId() + " " + agendItemDefinition.getAlways().getId());
160            }
161        }
162    }
163
164    private void crossCheckSubAgendaId(AgendaItemDefinition agendItemDefinition)
165            throws RiceIllegalArgumentException {
166        // if both are set they better match
167        if (agendItemDefinition.getSubAgendaId()!= null && agendItemDefinition.getSubAgenda() != null) {
168            if (!agendItemDefinition.getSubAgendaId().equals(agendItemDefinition.getSubAgenda().getId())) {
169                throw new RiceIllegalArgumentException("SubAgenda id does not match " + agendItemDefinition.getSubAgendaId() + " " + agendItemDefinition.getSubAgenda().getId());
170            }
171        }
172    }
173
174    private AgendaItemDefinition createUpdateRuleIfNeeded(AgendaItemDefinition agendaItemDefinition)
175            throws RiceIllegalArgumentException {
176        // no rule to create
177        if (agendaItemDefinition.getRule() == null) {
178            return agendaItemDefinition;
179        }
180
181        // create or update
182        RuleDefinition rule = null;
183        if (agendaItemDefinition.getRule().getId() != null) {
184            this.updateRule(agendaItemDefinition.getRule());
185            rule = this.getRule(agendaItemDefinition.getRule().getId());
186        } else {
187            rule = this.createRule(agendaItemDefinition.getRule());
188        }
189
190        AgendaItemDefinition.Builder agendaItemBuilder = AgendaItemDefinition.Builder.create(agendaItemDefinition);
191        RuleDefinition.Builder ruleBuilder = RuleDefinition.Builder.create(rule);
192        agendaItemBuilder.setRule(ruleBuilder);
193        agendaItemBuilder.setRuleId(ruleBuilder.getId());
194        return agendaItemBuilder.build();
195    }
196
197    private AgendaItemDefinition createWhenTrueAgendaItemIfNeeded(AgendaItemDefinition agendaItemDefinition) {
198        // nothing to create
199        if (agendaItemDefinition.getWhenTrue() == null) {
200            return agendaItemDefinition;
201        }
202
203        // ojb does not take care of terms and termparameters, recursively loop thru agendaitems to update terms
204        AgendaItemDefinition.Builder agendaItemBuilder = AgendaItemDefinition.Builder.create(agendaItemDefinition);
205        AgendaItemDefinition subAgendaItem = this.createUpdateAgendaItemIfNeeded(agendaItemDefinition.getWhenTrue());
206        agendaItemBuilder.setWhenTrue(AgendaItemDefinition.Builder.create(subAgendaItem));
207
208        return agendaItemBuilder.build();
209    }
210
211    private AgendaItemDefinition createWhenFalseAgendaItemIfNeeded(AgendaItemDefinition agendaItemDefinition) {
212        // nothing to create
213        if (agendaItemDefinition.getWhenFalse() == null) {
214            return agendaItemDefinition;
215        }
216
217        // ojb does not take care of terms and termparameters, recursively loop thru agendaitems to update terms
218        AgendaItemDefinition.Builder agendaItemBuilder = AgendaItemDefinition.Builder.create(agendaItemDefinition);
219        AgendaItemDefinition subAgendaItem = this.createUpdateAgendaItemIfNeeded(agendaItemDefinition.getWhenFalse());
220        agendaItemBuilder.setWhenFalse(AgendaItemDefinition.Builder.create(subAgendaItem));
221        return agendaItemBuilder.build();
222    }
223
224
225    private AgendaItemDefinition createAlwaysAgendaItemIfNeeded(AgendaItemDefinition agendaItemDefinition) {
226        // nothing to create
227        if (agendaItemDefinition.getAlways()== null) {
228            return agendaItemDefinition;
229        }
230
231        // ojb does not take care of terms and termparameters, recursively loop thru agendaitems to update terms
232        AgendaItemDefinition.Builder agendaItemBuilder = AgendaItemDefinition.Builder.create(agendaItemDefinition);
233        AgendaItemDefinition subAgendaItem = this.createUpdateAgendaItemIfNeeded(agendaItemDefinition.getAlways());
234        agendaItemBuilder.setAlways(AgendaItemDefinition.Builder.create(subAgendaItem));
235
236        return agendaItemBuilder.build();
237    }
238
239    private AgendaItemDefinition createSubAgendaIfNeeded(AgendaItemDefinition agendaItemDefinition) {
240        // nothing to create
241        if (agendaItemDefinition.getSubAgenda() == null) {
242            return agendaItemDefinition;
243        }
244
245        // ojb does not take care of terms and termparameters, recursively loop thru agendaitems to update terms
246        AgendaItemDefinition.Builder agendaItemBuilder = AgendaItemDefinition.Builder.create(agendaItemDefinition);
247        AgendaDefinition subAgenda = this.createAgenda(agendaItemDefinition.getSubAgenda());
248        agendaItemBuilder.setSubAgenda(AgendaDefinition.Builder.create(subAgenda));
249        agendaItemBuilder.setSubAgendaId(subAgenda.getId());
250
251        return agendaItemBuilder.build();
252    }
253
254    /**
255     * get the {@link NaturalLanguageTemplaterContract}
256     * @return the {@link NaturalLanguageTemplaterContract}
257     */
258    public NaturalLanguageTemplaterContract getTemplater() {
259        return templater;
260    }
261
262    /**
263     * set the {@link NaturalLanguageTemplaterContract}
264     * @param templater the {@link NaturalLanguageTemplaterContract} to set
265     */
266    public void setTemplater(NaturalLanguageTemplaterContract templater) {
267        this.templater = templater;
268    }
269
270    /**
271     * get the {@link TranslateBusinessMethods}
272     * @return the current {@link TranslateBusinessMethods}
273     */
274    public TranslateBusinessMethods getTranslateBusinessMethods() {
275        if(translationBusinessMethods  == null) {
276            this.translationBusinessMethods  = new KSTranslationUtility(this, getTermRepositoryService(), this.templater);
277        }
278        return this.translationBusinessMethods ;
279    }
280
281    /**
282     * get the {@link AgendaBoService}
283     * @return the {@link AgendaBoService}
284     */
285    public AgendaBoService getAgendaBoService() {
286        return agendaBoService;
287    }
288
289    /**
290     * set the {@link AgendaBoService}
291     * @param agendaBoService the {@link AgendaBoService} to set
292     */
293    public void setAgendaBoService(AgendaBoService agendaBoService) {
294        this.agendaBoService = agendaBoService;
295        super.setAgendaBoService(agendaBoService);
296    }
297
298}
299