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    
016    package org.kuali.rice.krms.impl.repository.language;
017    
018    import org.apache.commons.lang.StringUtils;
019    import org.apache.velocity.exception.VelocityException;
020    import org.kuali.rice.krms.api.repository.language.NaturalLanguageTemplate;
021    import org.kuali.rice.krms.api.repository.language.NaturalLanguageTemplaterContract;
022    import org.kuali.rice.krms.api.repository.proposition.PropositionParameterType;
023    import org.kuali.rice.krms.api.repository.term.TermDefinitionContract;
024    import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinitionContract;
025    import org.kuali.rice.krms.api.repository.type.KrmsTypeRepositoryService;
026    import org.kuali.rice.krms.impl.repository.KrmsTypeRepositoryServiceImpl;
027    import org.kuali.rice.krms.impl.repository.TermBoService;
028    import org.kuali.rice.krms.impl.repository.TermBoServiceImpl;
029    import org.kuali.student.common.util.VelocityTemplateEngine;
030    import org.kuali.student.r2.core.krms.naturallanguage.TermParameterTypes;
031    import org.kuali.student.r2.common.exceptions.DoesNotExistException;
032    import org.kuali.student.r2.common.exceptions.OperationFailedException;
033    import org.kuali.student.r2.core.krms.naturallanguage.Context;
034    import org.kuali.student.r2.core.krms.naturallanguage.ContextRegistry;
035    import org.slf4j.Logger;
036    import org.slf4j.LoggerFactory;
037    
038    import java.util.HashMap;
039    import java.util.List;
040    import java.util.Map;
041    
042    /**
043     * This class translates requirement components into a specific
044     * natural language. This class is not thread safe.
045     */
046    public 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    }