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     */
016    package org.kuali.rice.krms.impl.ui;
017    
018    
019    import org.apache.commons.collections.CollectionUtils;
020    import org.apache.commons.lang.StringUtils;
021    import org.kuali.rice.core.api.util.ConcreteKeyValue;
022    import org.kuali.rice.core.api.util.KeyValue;
023    import org.kuali.rice.krad.service.KRADServiceLocator;
024    import org.kuali.rice.krad.uif.control.UifKeyValuesFinderBase;
025    import org.kuali.rice.krad.uif.view.ViewModel;
026    import org.kuali.rice.krad.web.form.MaintenanceDocumentForm;
027    import org.kuali.rice.krms.impl.repository.CategoryBo;
028    import org.kuali.rice.krms.impl.repository.ContextValidTermBo;
029    import org.kuali.rice.krms.impl.repository.PropositionBo;
030    import org.kuali.rice.krms.impl.repository.TermBo;
031    import org.kuali.rice.krms.impl.repository.TermResolverBo;
032    import org.kuali.rice.krms.impl.repository.TermSpecificationBo;
033    import org.kuali.rice.krms.impl.util.KrmsImplConstants;
034    
035    import java.util.ArrayList;
036    import java.util.Collection;
037    import java.util.Collections;
038    import java.util.HashMap;
039    import java.util.Map;
040    import java.util.List;
041    
042    /**
043     * ValuesFinder used to populate the list of available Terms when creating/editing a proposition in a
044     * KRMS Rule.
045     *
046     * @author Kuali Rice Team (rice.collab@kuali.org)
047     */
048    public class ValidTermsValuesFinder extends UifKeyValuesFinderBase {
049    
050        /**
051         * get the value list for the Term dropdown in the KRMS rule editing UI
052         * @param model
053         * @return
054         */
055        @Override
056        public List<KeyValue> getKeyValues(ViewModel model) {
057            List<KeyValue> keyValues = new ArrayList<KeyValue>();
058    
059            MaintenanceDocumentForm maintenanceForm = (MaintenanceDocumentForm) model;
060            AgendaEditor agendaEditor = ((AgendaEditor) maintenanceForm.getDocument().getNewMaintainableObject().getDataObject());
061            String contextId = agendaEditor.getAgenda().getContextId();
062    
063            String selectedPropId = agendaEditor.getSelectedPropositionId();
064    
065            PropositionBo rootProposition = agendaEditor.getAgendaItemLine().getRule().getProposition();
066            PropositionBo editModeProposition = findPropositionUnderEdit(rootProposition);
067            String selectedCategoryId = (editModeProposition != null) ? editModeProposition.getCategoryId() : null;
068    
069            // Get all valid terms
070    
071            Collection<ContextValidTermBo> contextValidTerms = null;
072            contextValidTerms = KRADServiceLocator.getBusinessObjectService()
073                    .findMatching(ContextValidTermBo.class, Collections.singletonMap("contextId", contextId));
074    
075            List<String> termSpecIds = new ArrayList();
076            for (ContextValidTermBo validTerm : contextValidTerms) {
077                termSpecIds.add(validTerm.getTermSpecificationId());
078            }
079    
080            if (termSpecIds.size() > 0) { // if we don't have any valid terms, skip it
081                Collection<TermBo> terms = null;
082                Map<String,Object> criteria = new HashMap<String,Object>();
083                criteria.put("specificationId", termSpecIds);
084                terms = KRADServiceLocator.getBusinessObjectService().findMatchingOrderBy(TermBo.class, criteria, "description", true);
085    
086                // add all terms that are in the selected category (or else add 'em all if no category is selected)
087                for (TermBo term : terms) {
088                    String selectName = term.getDescription();
089    
090                    if (StringUtils.isBlank(selectName) || "null".equals(selectName)) {
091                        selectName = term.getSpecification().getName();
092                    }
093    
094                    if (!StringUtils.isBlank(selectedCategoryId)) {
095                        // only add if the term has the selected category
096                        if (isTermSpecificationInCategory(term.getSpecification(), selectedCategoryId)) {
097                            keyValues.add(new ConcreteKeyValue(term.getId(), selectName));
098                        }
099                    } else {
100                        keyValues.add(new ConcreteKeyValue(term.getId(), selectName));
101                    }
102                }
103    
104                //
105                // Add Parameterized Term Specs
106                //
107    
108                // get term resolvers for the given term specs
109                Collection<TermResolverBo> termResolvers =
110                        KRADServiceLocator.getBusinessObjectService().findMatchingOrderBy(
111                                TermResolverBo.class, Collections.singletonMap("outputId", termSpecIds), "name", true
112                        );
113    
114                // TODO: what if there is more than one resolver for a given term specification?
115    
116                if (termResolvers != null) for (TermResolverBo termResolver : termResolvers) {
117                    if (!CollectionUtils.isEmpty(termResolver.getParameterSpecifications())) {
118                        TermSpecificationBo output = termResolver.getOutput();
119    
120                        // filter by category
121                        if (StringUtils.isBlank(selectedCategoryId) ||
122                                isTermSpecificationInCategory(output, selectedCategoryId)) {
123                            String outputDescription = StringUtils.isBlank(output.getDescription())?output.getName():
124                                                                                                                                                                            output.getDescription();
125                            // we use a special prefix to differentiate these, as they are term spec ids instead of term ids.
126                            keyValues.add(new ConcreteKeyValue(KrmsImplConstants.PARAMETERIZED_TERM_PREFIX
127                                    + output.getId(), outputDescription
128                                    // build a string that indicates the number of parameters
129                                    + "(" + StringUtils.repeat("_", ",", termResolver.getParameterSpecifications().size()) +")"));
130                        }
131                    }
132                }
133            }
134    
135            return keyValues;
136        }
137    
138        /**
139         * @return true if the term specification is in the given category
140         */
141        private boolean isTermSpecificationInCategory(TermSpecificationBo termSpec, String categoryId) {
142            if (termSpec.getCategories() != null) {
143                for (CategoryBo category : termSpec.getCategories()) {
144                    if (categoryId.equals(category.getId())) {
145                        return true;
146                    }
147                }
148            }
149            return false;
150        }
151    
152        /**
153         * helper method to find the proposition under edit
154         */
155        private PropositionBo findPropositionUnderEdit(PropositionBo currentProposition) {
156            PropositionBo result = null;
157            if (currentProposition.getEditMode()) {
158                result = currentProposition;
159            } else {
160                if (currentProposition.getCompoundComponents() != null) {
161                    for (PropositionBo child : currentProposition.getCompoundComponents()) {
162                        result = findPropositionUnderEdit(child);
163                        if (result != null) break;
164                    }
165                }
166            }
167            return result;
168        }
169    
170    }