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.util;
017
018import org.apache.commons.lang.StringUtils;
019import org.kuali.rice.krms.api.repository.NaturalLanguageTree;
020import org.kuali.rice.krms.api.repository.RuleManagementService;
021import org.kuali.rice.krms.api.repository.language.NaturalLanguageUsage;
022import org.kuali.rice.krms.api.repository.proposition.PropositionDefinition;
023import org.kuali.rice.krms.api.repository.proposition.PropositionParameter;
024import org.kuali.rice.krms.api.repository.proposition.PropositionParameterContract;
025import org.kuali.rice.krms.api.repository.proposition.PropositionParameterType;
026import org.kuali.rice.krms.api.repository.term.TermDefinition;
027import org.kuali.rice.krms.api.repository.term.TermParameterDefinition;
028import org.kuali.rice.krms.dto.PropositionEditor;
029
030import java.io.Serializable;
031import java.util.ArrayList;
032import java.util.HashMap;
033import java.util.Iterator;
034import java.util.LinkedList;
035import java.util.List;
036import java.util.Map;
037import java.util.Queue;
038
039/**
040 * @author Kuali Student Team
041 */
042public class NaturalLanguageHelper {
043
044    private RuleManagementService ruleManagementService;
045
046    private Map<String, String> usageMap = new HashMap<String, String>();
047
048    /**
049     * This method should set the natural language only for the given proposition. It does not
050     * do a recursive call through the tree structure.
051     *
052     * @param proposition
053     * @param usageName
054     */
055    public void setNaturalLanguageForUsage(PropositionEditor proposition, String usageName, String namespace){
056        //Setup the Proposition
057        List<PropositionParameter.Builder> parameters = new ArrayList<PropositionParameter.Builder>();
058        if(proposition.getParameters()!=null){  //Parameters on Compound Propositions could be null.
059            for(PropositionParameterContract parameter : proposition.getParameters()){
060                PropositionParameter.Builder parmBuilder = PropositionParameter.Builder.create(parameter);
061
062                //Add the edited term.
063                if(parameter.getParameterType().equals(PropositionParameterType.TERM.getCode())){
064                    if(proposition.getTerm()!=null){
065                        TermDefinition.Builder termBuilder = TermDefinition.Builder.create(proposition.getTerm());
066                        for (Map.Entry<String, String> entry : proposition.getNlParameters().entrySet()) {
067                            termBuilder.getParameters().add(TermParameterDefinition.Builder.create(null, null, entry.getKey(), entry.getValue()));
068                        }
069                        parmBuilder.setTermValue(termBuilder.build());
070                    }
071                }
072                parameters.add(parmBuilder);
073            }
074        }
075
076        //Create the propbuilder but don set compound editors here, we only want to get the nl for current proposition
077        PropositionDefinition.Builder propBuilder = PropositionDefinition.Builder.create(proposition.getId(),
078                proposition.getPropositionTypeCode(), proposition.getRuleId(), proposition.getTypeId(), parameters);
079
080        //Build the tree.
081        TreeIterator nlTree = this.buildNaturalLanguageTree(propBuilder, this.getNaturalLanguageUsageId(usageName, namespace));
082        this.setTranslatedNaturalLanguage(proposition, usageName, nlTree);
083    }
084
085    /**
086     * This method sets the natural language descriptions for the given proposition and all its child propositions as
087     * well.
088     *
089     * @param proposition
090     * @param usageName
091     */
092    public void setNaturalLanguageTreeForUsage(PropositionEditor proposition, String usageName, String namespace){
093        if(proposition==null){
094            return;
095        }
096
097        PropositionDefinition.Builder propBuilder = PropositionDefinition.Builder.create(proposition);
098        TreeIterator nlTree = this.buildNaturalLanguageTree(propBuilder, this.getNaturalLanguageUsageId(usageName, namespace));
099        this.setTranslatedNaturalLanguage(proposition, usageName, nlTree);
100    }
101
102    private TreeIterator buildNaturalLanguageTree(PropositionDefinition.Builder propBuilder, String usageId){
103        NaturalLanguageTree nlTree = this.getRuleManagementService().translateNaturalLanguageTreeForProposition(usageId, propBuilder.build(), "en");
104        return new TreeIterator(nlTree);
105    }
106
107    private void setTranslatedNaturalLanguage(PropositionEditor proposition, String usageName, TreeIterator nlDescriptions){
108        if(!nlDescriptions.hasNext()){
109            return;
110        }
111
112        proposition.setNaturalLanguageForUsage(usageName, nlDescriptions.next());
113
114        if (proposition.getCompoundEditors() != null){
115            for (PropositionEditor child : proposition.getCompoundEditors()){
116                setTranslatedNaturalLanguage(child, usageName, nlDescriptions);
117            }
118        }
119    }
120
121    private String getNaturalLanguageUsageId(String usageName, String namespace){
122        //usageName cannot be null or blank
123        if ((usageName == null) || (StringUtils.isBlank(usageName))){
124            return null;
125        }
126
127        //Retrieve usageId form map.
128        String usageId = usageMap.get(usageName);
129        if (usageId == null){
130
131            //Retrieve usage from service if usageId not on map.
132            NaturalLanguageUsage usage = this.getRuleManagementService().getNaturalLanguageUsageByNameAndNamespace(usageName,
133                    namespace);
134
135            //Set the usage id to the map.
136            if (usage != null){
137                usageId = usage.getId();
138                usageMap.put(usageName, usageId);
139            }
140        }
141        return usageId;
142    }
143
144    public RuleManagementService getRuleManagementService() {
145        return ruleManagementService;
146    }
147
148    public void setRuleManagementService(RuleManagementService ruleManagementService) {
149        this.ruleManagementService = ruleManagementService;
150    }
151
152    /**
153     * Put the natural language descriptions in a queue and retrieve them in
154     * the same order as the propostion tree.
155     */
156    protected class TreeIterator implements Serializable, Iterator<String> {
157
158        private Queue<String> nl;
159
160        public TreeIterator(NaturalLanguageTree tree){
161            nl = new LinkedList<String>();
162            this.addToStack(tree);
163        }
164
165        private void addToStack(NaturalLanguageTree tree){
166            if (tree == null){
167                return;
168            }
169
170            nl.offer(tree.getNaturalLanguage());
171            if (tree.getChildren() != null){
172                for (NaturalLanguageTree child : tree.getChildren()){
173                    addToStack(child);
174                }
175            }
176        }
177
178        @Override
179        public boolean hasNext() {
180            return !nl.isEmpty();
181        }
182
183        @Override
184        public String next() {
185            return nl.poll();
186        }
187
188        @Override
189        public void remove() {
190            //To change body of implemented methods use File | Settings | File Templates.
191        }
192    }
193}