001    package org.kuali.rice.krms.util;
002    
003    import org.apache.commons.lang.StringUtils;
004    import org.kuali.rice.krms.api.repository.NaturalLanguageTree;
005    import org.kuali.rice.krms.api.repository.RuleManagementService;
006    import org.kuali.rice.krms.api.repository.language.NaturalLanguageUsage;
007    import org.kuali.rice.krms.api.repository.proposition.PropositionDefinition;
008    import org.kuali.rice.krms.api.repository.proposition.PropositionParameter;
009    import org.kuali.rice.krms.api.repository.proposition.PropositionParameterContract;
010    import org.kuali.rice.krms.api.repository.proposition.PropositionParameterType;
011    import org.kuali.rice.krms.api.repository.term.TermDefinition;
012    import org.kuali.rice.krms.api.repository.term.TermParameterDefinition;
013    import org.kuali.rice.krms.dto.PropositionEditor;
014    import org.kuali.rice.krms.dto.TermEditor;
015    import org.kuali.rice.krms.tree.AbstractTreeBuilder;
016    import org.kuali.student.enrollment.class2.courseoffering.service.decorators.PermissionServiceConstants;
017    import org.kuali.student.krms.naturallanguage.util.KsKrmsConstants;
018    
019    import java.io.Serializable;
020    import java.util.ArrayList;
021    import java.util.HashMap;
022    import java.util.Iterator;
023    import java.util.LinkedList;
024    import java.util.List;
025    import java.util.Map;
026    import 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     */
035    public 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    }