001/** 002 * Copyright 2005-2014 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.language; 017 018import org.apache.commons.lang.StringUtils; 019import org.apache.velocity.exception.VelocityException; 020import org.kuali.rice.krms.api.repository.language.NaturalLanguageTemplate; 021import org.kuali.rice.krms.api.repository.language.NaturalLanguageTemplaterContract; 022import org.kuali.rice.krms.api.repository.proposition.PropositionParameterType; 023import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinitionContract; 024import org.kuali.rice.krms.api.repository.type.KrmsTypeRepositoryService; 025import org.kuali.rice.krms.impl.repository.KrmsTypeRepositoryServiceImpl; 026import org.slf4j.Logger; 027import org.slf4j.LoggerFactory; 028 029import java.util.HashMap; 030import java.util.List; 031import java.util.Map; 032 033/** 034 * This class translates requirement components into a specific 035 * natural language. This class is not thread safe. 036 */ 037public class PropositionNaturalLanguageTemplater implements NaturalLanguageTemplaterContract { 038 /** 039 * SLF4J logging framework 040 */ 041 private final static Logger logger = LoggerFactory.getLogger(PropositionNaturalLanguageTemplater.class); 042 043 private TranslationContextRegistry<TranslationContext> translationContextRegistry; 044 045 private KrmsTypeRepositoryService krmsTypeRepositoryService = new KrmsTypeRepositoryServiceImpl(); 046 047 /** 048 * Relational operator token. 049 */ 050 public final static String OPERATOR_TOKEN = "relationalOperator"; 051 /** 052 * An integer value token. 053 */ 054 public final static String CONSTANT_VALUE_TOKEN = "intValue"; 055 056 /** 057 * Velocity template engine. 058 */ 059 private VelocityTemplateEngine templateEngine = new VelocityTemplateEngine(); 060 061 062 /** 063 * Constructs a new proposition natural language templater. 064 */ 065 public PropositionNaturalLanguageTemplater() { 066 } 067 068 069 /** 070 * Sets the template context registry. 071 * 072 * @param translationContextRegistry Template context registry 073 */ 074 public void setTranslationContextRegistry( 075 final TranslationContextRegistry<TranslationContext> translationContextRegistry) { 076 this.translationContextRegistry = translationContextRegistry; 077 } 078 079 public String translate(NaturalLanguageTemplate naturalLanguageTemplate, Map<String, Object> parametersMap) { 080 081 if (naturalLanguageTemplate == null) { 082 return StringUtils.EMPTY; 083 } 084 085 Map<String, Object> contextMap = null; 086 try { 087 contextMap = buildContextMap(naturalLanguageTemplate.getTypeId(), parametersMap); 088 } catch (Exception e) { 089 e.printStackTrace(); //TODO hand back to service. 090 } 091 092 try { 093 String nl = this.templateEngine.evaluate(contextMap, naturalLanguageTemplate.getTemplate()); 094 if (logger.isInfoEnabled()) { 095 logger.info("nl=" + nl); 096 } 097 return nl; 098 } catch (VelocityException e) { 099 String msg = "Generating template for proposition failed: template='" + naturalLanguageTemplate.getTemplate() + "', contextMap=" + contextMap; 100 logger.error(msg, e); 101 //TODO hand back to service throw new Exception(msg); 102 } 103 return "Error"; 104 } 105 106 /** 107 * Builds a proposition type context map. 108 * 109 * @param typeId the natural language template id 110 * @param parametersMap map containing the proposition parameter types and their values 111 * @throws java.lang.Exception Creating context map failed 112 */ 113 private Map<String, Object> buildContextMap(String typeId, Map<String, Object> parametersMap) throws Exception { 114 115 Map<String, Object> contextMap = new HashMap<String, Object>(); 116 //Add proposition constant to contextMap. 117 if (parametersMap.containsKey(PropositionParameterType.CONSTANT.getCode())) { 118 String constantString = (String) parametersMap.get(PropositionParameterType.CONSTANT.getCode()); 119 if (StringUtils.isNumeric(constantString)) { 120 contextMap.put(CONSTANT_VALUE_TOKEN, Integer.valueOf(constantString)); 121 } else { 122 contextMap.put(CONSTANT_VALUE_TOKEN, constantString); 123 } 124 } 125 //Add proposition operator to contextMap. 126 if (parametersMap.containsKey(PropositionParameterType.OPERATOR.getCode())) { 127 String operatorString = (String) parametersMap.get(PropositionParameterType.OPERATOR.getCode()); 128 contextMap.put(OPERATOR_TOKEN, operatorString); 129 } 130 //Access type service to retrieve type name. 131 KrmsTypeDefinitionContract type = getKrmsTypeRepositoryService().getTypeById(typeId); 132 List<TranslationContext> translationContextList = this.translationContextRegistry.get(type.getName()); 133 if (translationContextList == null || translationContextList.isEmpty()) { 134 return contextMap; 135 } 136 137 for (TranslationContext translationContext : translationContextList) { 138 Map<String, Object> cm = translationContext.createContextMap(parametersMap); 139 contextMap.putAll(cm); 140 } 141 142 if (logger.isInfoEnabled()) { 143 logger.info("contextMap=" + contextMap); 144 } 145 return contextMap; 146 } 147 148 149 private KrmsTypeRepositoryService getKrmsTypeRepositoryService() { 150 return krmsTypeRepositoryService; 151 } 152 153 public void setKrmsTypeRepositoryService(KrmsTypeRepositoryService krmsTypeRepositoryService) { 154 this.krmsTypeRepositoryService = krmsTypeRepositoryService; 155 } 156 157}