001/**
002 * Copyright 2010 The Kuali Foundation Licensed under the
003 * Educational Community License, Version 2.0 (the "License"); you may
004 * not use this file except in compliance with the License. You may
005 * obtain a copy of the License at
006 *
007 * http://www.osedu.org/licenses/ECL-2.0
008 *
009 * Unless required by applicable law or agreed to in writing,
010 * software distributed under the License is distributed on an "AS IS"
011 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
012 * or implied. See the License for the specific language governing
013 * permissions and limitations under the License.
014 */
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.term.TermDefinitionContract;
024import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinitionContract;
025import org.kuali.rice.krms.api.repository.type.KrmsTypeRepositoryService;
026import org.kuali.rice.krms.impl.repository.KrmsTypeRepositoryServiceImpl;
027import org.kuali.rice.krms.impl.repository.TermBoService;
028import org.kuali.rice.krms.impl.repository.TermBoServiceImpl;
029import org.kuali.student.common.util.VelocityTemplateEngine;
030import org.kuali.student.r2.core.krms.naturallanguage.TermParameterTypes;
031import org.kuali.student.r2.common.exceptions.DoesNotExistException;
032import org.kuali.student.r2.common.exceptions.OperationFailedException;
033import org.kuali.student.r2.core.krms.naturallanguage.Context;
034import org.kuali.student.r2.core.krms.naturallanguage.ContextRegistry;
035import org.slf4j.Logger;
036import org.slf4j.LoggerFactory;
037
038import java.util.HashMap;
039import java.util.List;
040import java.util.Map;
041
042/**
043 * This class translates requirement components into a specific
044 * natural language. This class is not thread safe.
045 */
046public class PropositionNaturalLanguageTemplater implements NaturalLanguageTemplaterContract {
047    /**
048     * SLF4J logging framework
049     */
050    private final static Logger logger = LoggerFactory.getLogger(PropositionNaturalLanguageTemplater.class);
051
052    private ContextRegistry<Context> contextRegistry;
053
054    private KrmsTypeRepositoryService krmsTypeRepositoryService = new KrmsTypeRepositoryServiceImpl();
055
056    /**
057     * Relational operator token.
058     */
059    public final static String OPERATOR_TOKEN = "relationalOperator";
060    /**
061     * An integer value token.
062     */
063    public final static String CONSTANT_VALUE_TOKEN = "intValue";
064
065    /**
066     * Velocity template engine.
067     */
068    private VelocityTemplateEngine templateEngine = new VelocityTemplateEngine();
069
070
071    /**
072     * Constructs a new proposition natural language templater.
073     */
074    public PropositionNaturalLanguageTemplater() {
075    }
076
077
078    /**
079     * Sets the template context registry.
080     *
081     * @param contextRegistry Template context registry
082     */
083    public void setContextRegistry(final ContextRegistry<Context> contextRegistry) {
084        this.contextRegistry = contextRegistry;
085    }
086
087    public String translate(NaturalLanguageTemplate naturalLanguageTemplate, Map<String, Object> parametersMap) {
088
089        if (naturalLanguageTemplate == null) {
090            return StringUtils.EMPTY;
091        }
092
093        Map<String, Object> contextMap = null;
094        try {
095            contextMap = buildContextMap(naturalLanguageTemplate.getTypeId(), parametersMap);
096        } catch (Exception e) {
097            e.printStackTrace();  //TODO hand back to service.
098        }
099
100        try {
101            String nl = this.templateEngine.evaluate(contextMap, naturalLanguageTemplate.getTemplate());
102            if (logger.isInfoEnabled()) {
103                logger.info("nl=" + nl);
104            }
105            return nl;
106        } catch (VelocityException e) {
107            String msg = "Generating template for proposition failed: template='" + naturalLanguageTemplate.getTemplate() + "', contextMap=" + contextMap;
108            logger.error(msg, e);
109            //TODO hand back to service throw new Exception(msg);
110        }
111        return "Error";
112    }
113
114    /**
115     * Builds a proposition type context map.
116     *
117     * @param typeId        the natural language template id
118     * @param parametersMap map containing the proposition parameter types and their values
119     * @throws java.lang.Exception Creating context map failed
120     */
121    private Map<String, Object> buildContextMap(String typeId, Map<String, Object> parametersMap) throws Exception {
122
123        Map<String, Object> contextMap = new HashMap<String, Object>();
124        //Add proposition constant to contextMap.
125        if (parametersMap.containsKey(PropositionParameterType.CONSTANT.getCode())) {
126            contextMap.put(CONSTANT_VALUE_TOKEN, (String) parametersMap.get(PropositionParameterType.CONSTANT.getCode()));
127        }
128        //Add proposition operator to contextMap.
129        if (parametersMap.containsKey(PropositionParameterType.OPERATOR.getCode())) {
130            contextMap.put(OPERATOR_TOKEN, (String) parametersMap.get(PropositionParameterType.OPERATOR.getCode()));
131        }
132        //Access type service to retrieve type name.
133        KrmsTypeDefinitionContract type = getKrmsTypeRepositoryService().getTypeById(typeId);
134        List<Context> contextList = this.contextRegistry.get(type.getName());
135        if (contextList == null || contextList.isEmpty()) {
136            return contextMap;
137        }
138
139        for (Context context : contextList) {
140            Map<String, Object> cm = context.createContextMap(parametersMap, new org.kuali.student.r2.common.dto.ContextInfo());  // KS contextInfo is not passed through here
141            contextMap.putAll(cm);
142        }
143
144        if (logger.isInfoEnabled()) {
145            logger.info("contextMap=" + contextMap);
146        }
147        return contextMap;
148    }
149
150
151    private KrmsTypeRepositoryService getKrmsTypeRepositoryService() {
152        return krmsTypeRepositoryService;
153    }
154
155    public void setKrmsTypeRepositoryService(KrmsTypeRepositoryService krmsTypeRepositoryService) {
156        this.krmsTypeRepositoryService = krmsTypeRepositoryService;
157    }
158
159}