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