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