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 }