View Javadoc

1   /**
2    * Copyright 2005-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  /*
17   * To change this template, choose Tools | Templates
18   * and open the template in the editor.
19   */
20  package org.kuali.rice.krms.impl.repository;
21  
22  import java.util.ArrayList;
23  import java.util.LinkedHashMap;
24  import java.util.List;
25  import java.util.Map;
26  
27  import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
28  import org.kuali.rice.krms.api.repository.NaturalLanguageTree;
29  import org.kuali.rice.krms.api.repository.RuleManagementService;
30  import org.kuali.rice.krms.api.repository.TranslateBusinessMethods;
31  import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition;
32  import org.kuali.rice.krms.api.repository.agenda.AgendaItemDefinition;
33  import org.kuali.rice.krms.api.repository.language.NaturalLanguageTemplate;
34  import org.kuali.rice.krms.api.repository.language.NaturalLanguageTemplaterContract;
35  import org.kuali.rice.krms.api.repository.proposition.PropositionDefinition;
36  import org.kuali.rice.krms.api.repository.proposition.PropositionParameter;
37  import org.kuali.rice.krms.api.repository.proposition.PropositionParameterType;
38  import org.kuali.rice.krms.api.repository.proposition.PropositionType;
39  import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
40  import org.kuali.rice.krms.api.repository.term.TermDefinition;
41  import org.kuali.rice.krms.api.repository.term.TermParameterDefinition;
42  import org.kuali.rice.krms.api.repository.term.TermRepositoryService;
43  
44  /**
45   * @author nwright
46   */
47  public class TranslationUtility implements TranslateBusinessMethods {
48  
49      private RuleManagementService ruleManagementService;
50      private NaturalLanguageTemplaterContract templater;
51  
52      public TranslationUtility(RuleManagementService ruleManagementService,
53              NaturalLanguageTemplaterContract templater) {
54          this.ruleManagementService = ruleManagementService;
55          this.templater = templater;
56      }
57  
58      public RuleManagementService getRuleManagementService() {
59          return ruleManagementService;
60      }
61  
62      public void setRuleManagementService(RuleManagementService ruleManagementService) {
63          this.ruleManagementService = ruleManagementService;
64      }
65  
66      public NaturalLanguageTemplaterContract getTemplater() {
67          return templater;
68      }
69  
70      public void setTemplater(NaturalLanguageTemplaterContract templater) {
71          this.templater = templater;
72      }
73  
74      @Override
75      public String translateNaturalLanguageForObject(String naturalLanguageUsageId, String typeId, String krmsObjectId, String languageCode)
76              throws RiceIllegalArgumentException {
77  
78          PropositionDefinition proposition = null;
79          // TODO: find out what RICE intended for this typeId? Was it supposed to be the Simple Class name?
80          if (typeId.equals("proposition")) {
81              proposition = this.ruleManagementService.getProposition(krmsObjectId);
82              if (proposition == null) {
83                  throw new RiceIllegalArgumentException(krmsObjectId + " is not an Id for a proposition");
84              }
85          } else if (typeId.equals("agenda")) {
86              AgendaDefinition agenda = this.ruleManagementService.getAgenda(krmsObjectId);
87              if (agenda == null) {
88                  throw new RiceIllegalArgumentException(krmsObjectId + " is not an Id for an agenda");
89              }
90              if (agenda.getFirstItemId() == null) {
91                  throw new RiceIllegalArgumentException("Agenda has no first item");
92              }
93              AgendaItemDefinition item = this.ruleManagementService.getAgendaItem(agenda.getFirstItemId());
94              if (item.getRuleId() == null) {
95                  throw new RiceIllegalArgumentException("Only simple agenda's composed of one item that holds a rule is supported at this time");
96              }
97              RuleDefinition rule = this.ruleManagementService.getRule(item.getRuleId());
98              proposition = rule.getProposition();
99              if (proposition == null) {
100                 throw new RiceIllegalArgumentException("The agenda's rule has a proposition that is null");
101             }
102         }
103         String propositionTypeId = proposition.getTypeId();
104         NaturalLanguageTemplate naturalLanguageTemplate =
105                 this.ruleManagementService.findNaturalLanguageTemplateByLanguageCodeTypeIdAndNluId(languageCode,
106                 propositionTypeId,
107                 naturalLanguageUsageId);
108         if (naturalLanguageTemplate == null) {
109             throw new RiceIllegalArgumentException("no template found for " + languageCode
110                     + " " + typeId
111                     + " " + naturalLanguageUsageId);
112         }
113         return this.translateNaturalLanguageForProposition(naturalLanguageUsageId, proposition, languageCode);
114     }
115 
116     @Override
117     public String translateNaturalLanguageForProposition(String naturalLanguageUsageId,
118             PropositionDefinition proposition, String languageCode)
119             throws RiceIllegalArgumentException {
120         NaturalLanguageTemplate naturalLanguageTemplate =
121                 this.ruleManagementService.findNaturalLanguageTemplateByLanguageCodeTypeIdAndNluId(languageCode,
122                 proposition.getTypeId(), naturalLanguageUsageId);
123         if (naturalLanguageTemplate == null) {
124             throw new RiceIllegalArgumentException(languageCode + "." + proposition.getTypeId() + "." + naturalLanguageUsageId);
125         }
126         Map<String, Object> contextMap;
127         if (proposition.getPropositionTypeCode().equals(PropositionType.SIMPLE.getCode())) {
128             contextMap = this.buildSimplePropositionContextMap(proposition);
129         } else {
130             contextMap = this.buildCompoundPropositionContextMap(null, proposition, null);
131         }
132         return templater.translate(naturalLanguageTemplate, contextMap);
133     }
134 
135     @Override
136     public NaturalLanguageTree translateNaturalLanguageTreeForProposition(String naturalLanguageUsageId,
137             PropositionDefinition proposition,
138             String languageCode) throws RiceIllegalArgumentException {
139         NaturalLanguageTemplate naturalLanguageTemplate = null;
140         //Continue if typeid is null, some children may not be initialized yet.
141         if (proposition.getTypeId() != null) {
142             naturalLanguageTemplate = this.ruleManagementService.findNaturalLanguageTemplateByLanguageCodeTypeIdAndNluId(languageCode,
143                     proposition.getTypeId(), naturalLanguageUsageId);
144             if (naturalLanguageTemplate == null) {
145                 throw new RiceIllegalArgumentException(languageCode + "." + proposition.getTypeId() + "." + naturalLanguageUsageId);
146             }
147         }
148 
149         if (proposition.getPropositionTypeCode().equals(PropositionType.SIMPLE.getCode())) {
150             NaturalLanguageTree.Builder tree = NaturalLanguageTree.Builder.create();
151             Map<String, Object> contextMap = this.buildSimplePropositionContextMap(proposition);
152             String naturalLanguage = templater.translate(naturalLanguageTemplate, contextMap);
153             tree.setNaturalLanguage(naturalLanguage);
154             return tree.build();
155         }
156         if (proposition.getPropositionTypeCode().equals(PropositionType.COMPOUND.getCode())) {
157             NaturalLanguageTree.Builder tree = NaturalLanguageTree.Builder.create();
158             Map<String, Object> contextMap = this.buildCompoundPropositionContextMap(naturalLanguageUsageId, proposition, languageCode);
159             String naturalLanguage = templater.translate(naturalLanguageTemplate, contextMap);
160             tree.setNaturalLanguage(naturalLanguage);
161 
162             //Null check because newly created compound propositions should also be translateable.
163             if(proposition.getCompoundComponents()!=null){
164                 List<NaturalLanguageTree> children = new ArrayList<NaturalLanguageTree>();
165                 for (PropositionDefinition child : proposition.getCompoundComponents()) {
166                     children.add(this.translateNaturalLanguageTreeForProposition(naturalLanguageUsageId, child, languageCode));
167                 }
168                 tree.setChildren(children);
169             }
170 
171             return tree.build();
172         }
173         throw new RiceIllegalArgumentException("Unknown proposition type: " + proposition.getPropositionTypeCode());
174     }
175 
176     protected Map<String, Object> buildSimplePropositionContextMap(PropositionDefinition proposition) {
177         if (!proposition.getPropositionTypeCode().equals(PropositionType.SIMPLE.getCode())) {
178             throw new RiceIllegalArgumentException("proposition is not simple " + proposition.getPropositionTypeCode() + " " + proposition.getId() + proposition.getDescription());
179         }
180         Map<String, Object> contextMap = new LinkedHashMap<String, Object>();
181         for (PropositionParameter param : proposition.getParameters()) {
182             if (param.getParameterType().equals(PropositionParameterType.TERM.getCode())) {
183                 if (param.getTermValue() != null) {
184                     for (TermParameterDefinition termParam : param.getTermValue().getParameters()) {
185                         contextMap.put(termParam.getName(), termParam.getValue());
186                     }
187                 } else {
188                     contextMap.put(param.getParameterType(), param.getValue());
189                 }
190             } else {
191                 contextMap.put(param.getParameterType(), param.getValue());
192             }
193         }
194         return contextMap;
195     }
196     public static final String COMPOUND_COMPONENTS = "compoundComponent";
197 
198     protected Map<String, Object> buildCompoundPropositionContextMap(String naturalLanguageUsageId, PropositionDefinition proposition, String languageCode) {
199         if (!proposition.getPropositionTypeCode().equals(PropositionType.COMPOUND.getCode())) {
200             throw new RiceIllegalArgumentException("proposition us not compound " + proposition.getPropositionTypeCode() + " " + proposition.getId() + proposition.getDescription());
201         }
202         Map<String, Object> contextMap = new LinkedHashMap<String, Object>();
203         /*List<String> children = new ArrayList<String>();
204          for (PropositionDefinition param : proposition.getCompoundComponents()) {
205          children.add(this.translateNaturalLanguageForProposition(naturalLanguageUsageId, proposition, languageCode));
206          }
207          contextMap.put(COMPOUND_COMPONENTS, children);*/
208         return contextMap;
209     }
210 
211     protected String translateCompoundProposition(PropositionDefinition proposition, String naturalLanguageUsageId, String languageCode)
212             throws RiceIllegalArgumentException {
213         if (!proposition.getPropositionTypeCode().equals(PropositionType.COMPOUND.getCode())) {
214             throw new RiceIllegalArgumentException("proposition us not compound " + proposition.getPropositionTypeCode() + " " + proposition.getId() + proposition.getDescription());
215         }
216         String compoundNaturalLanguageTypeId = this.calcCompoundNaturalLanguageTypeId(proposition.getCompoundOpCode());
217         // TODO: make sure we cache the AND and OR templates
218         NaturalLanguageTemplate template = this.ruleManagementService.findNaturalLanguageTemplateByLanguageCodeTypeIdAndNluId(languageCode,
219                 compoundNaturalLanguageTypeId, naturalLanguageUsageId);
220         Map<String, Object> contextMap = this.buildCompoundPropositionContextMap(naturalLanguageUsageId, proposition, languageCode);
221         return this.templater.translate(template, contextMap);
222 
223     }
224 
225     protected String calcCompoundNaturalLanguageTypeId(String compoundOpCode) throws RiceIllegalArgumentException {
226         if (compoundOpCode.equals("a")) {
227             return "kuali.compound.proposition.op.code." + "and";
228         }
229         if (compoundOpCode.equals("o")) {
230             return "kuali.compound.proposition.op.code." + "or";
231         }
232         throw new RiceIllegalArgumentException("unsupported compound op code " + compoundOpCode);
233     }
234 
235     protected String translateSimpleProposition(NaturalLanguageTemplate naturalLanguageTemplate,
236             PropositionDefinition proposition)
237             throws RiceIllegalArgumentException {
238         if (!proposition.getPropositionTypeCode().equals(PropositionType.SIMPLE.getCode())) {
239             throw new RiceIllegalArgumentException("proposition not simple " + proposition.getPropositionTypeCode() + " " + proposition.getId() + proposition.getDescription());
240         }
241         Map<String, Object> contextMap = this.buildSimplePropositionContextMap(proposition);
242         return templater.translate(naturalLanguageTemplate, contextMap);
243     }
244 }