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.krad.uif.control; 017 018 import org.apache.commons.lang.StringUtils; 019 import org.kuali.rice.kim.api.identity.Person; 020 import org.kuali.rice.kim.api.identity.PersonService; 021 import org.kuali.rice.kim.api.identity.principal.Principal; 022 import org.kuali.rice.kim.api.services.KimApiServiceLocator; 023 import org.kuali.rice.krad.datadictionary.parse.BeanTag; 024 import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute; 025 import org.kuali.rice.krad.uif.field.InputField; 026 import org.kuali.rice.krad.uif.util.ComponentFactory; 027 import org.kuali.rice.krad.uif.util.ScriptUtils; 028 import org.kuali.rice.krad.uif.view.View; 029 import org.kuali.rice.krad.uif.component.Component; 030 import org.kuali.rice.krad.uif.component.MethodInvokerConfig; 031 import org.kuali.rice.krad.uif.field.AttributeQuery; 032 import org.kuali.rice.krad.uif.widget.QuickFinder; 033 034 import java.util.HashMap; 035 import java.util.Map; 036 037 /** 038 * Represents a user control, which is a special control to handle 039 * the input of a Person 040 * 041 * @author Kuali Rice Team (rice.collab@kuali.org) 042 */ 043 @BeanTag(name = "kimPersonControl-bean", parent = "Uif-KimPersonControl") 044 public class UserControl extends TextControl implements FilterableLookupCriteriaControl { 045 private static final long serialVersionUID = 7468340793076585869L; 046 047 private String principalIdPropertyName; 048 private String personNamePropertyName; 049 private String personObjectPropertyName; 050 051 public UserControl() { 052 super(); 053 } 054 055 /** 056 * @see org.kuali.rice.krad.uif.component.ComponentBase#performApplyModel(org.kuali.rice.krad.uif.view.View, 057 * java.lang.Object, org.kuali.rice.krad.uif.component.Component) 058 */ 059 @Override 060 public void performApplyModel(View view, Object model, Component parent) { 061 super.performApplyModel(view, model, parent); 062 063 if (!(parent instanceof InputField)) { 064 return; 065 } 066 067 InputField field = (InputField) parent; 068 field.getAdditionalHiddenPropertyNames().add(principalIdPropertyName); 069 070 if (!field.isReadOnly()) { 071 // add information fields 072 if (StringUtils.isNotBlank(personNamePropertyName)) { 073 field.getPropertyNamesForAdditionalDisplay().add(personNamePropertyName); 074 } else { 075 field.getPropertyNamesForAdditionalDisplay().add(personObjectPropertyName + ".name"); 076 } 077 078 // setup script to clear id field when name is modified 079 String idPropertyPath = field.getBindingInfo().getPropertyAdjustedBindingPath(principalIdPropertyName); 080 String onChangeScript = "setValue('" + ScriptUtils.escapeName(idPropertyPath) + "','');"; 081 082 if (StringUtils.isNotBlank(getOnChangeScript())) { 083 onChangeScript = getOnChangeScript() + onChangeScript; 084 } 085 setOnChangeScript(onChangeScript); 086 } 087 088 if (field.isReadOnly() && StringUtils.isBlank(field.getReadOnlyDisplaySuffixPropertyName())) { 089 if (StringUtils.isNotBlank(personNamePropertyName)) { 090 field.setReadOnlyDisplaySuffixPropertyName(personNamePropertyName); 091 } else { 092 field.setReadOnlyDisplaySuffixPropertyName(personObjectPropertyName + ".name"); 093 } 094 } 095 096 // setup field query for displaying name 097 AttributeQuery attributeQuery = new AttributeQuery(); 098 099 MethodInvokerConfig methodInvokerConfig = new MethodInvokerConfig(); 100 PersonService personService = KimApiServiceLocator.getPersonService(); 101 methodInvokerConfig.setTargetObject(personService); 102 103 attributeQuery.setQueryMethodInvokerConfig(methodInvokerConfig); 104 attributeQuery.setQueryMethodToCall("getPersonByPrincipalName"); 105 attributeQuery.getQueryMethodArgumentFieldList().add(field.getPropertyName()); 106 attributeQuery.getReturnFieldMapping().put("principalId", principalIdPropertyName); 107 108 if (StringUtils.isNotBlank(personNamePropertyName)) { 109 attributeQuery.getReturnFieldMapping().put("name", personNamePropertyName); 110 } else { 111 attributeQuery.getReturnFieldMapping().put("name", personObjectPropertyName + ".name"); 112 } 113 field.setAttributeQuery(attributeQuery); 114 115 // // TODO: revisit this, need to hook new quickfinder into lifecycle 116 // buildUserQuickfinder(view, field); 117 } 118 119 /** 120 * @see FilterableLookupCriteriaControl#filterSearchCriteria(String, java.util.Map) 121 */ 122 @Override 123 public Map<String, String> filterSearchCriteria(String propertyName, Map<String, String> searchCriteria) { 124 Map<String, String> filteredSearchCriteria = new HashMap<String, String>(searchCriteria); 125 126 // check valid principalName 127 // ToDo: move the principalId check and setting to the validation stage. At that point the personName should 128 // be set as well or an error be displayed to the user that the principalName is invalid. 129 String principalName = searchCriteria.get(propertyName); 130 if (StringUtils.isNotBlank(principalName)) { 131 Principal principal = KimApiServiceLocator.getIdentityService().getPrincipalByPrincipalName(principalName); 132 if (principal == null) { 133 return null; 134 } else { 135 filteredSearchCriteria.put(principalIdPropertyName, principal.getPrincipalId()); 136 } 137 } 138 139 // filter 140 filteredSearchCriteria.remove(propertyName); 141 filteredSearchCriteria.remove(personNamePropertyName); 142 143 return filteredSearchCriteria; 144 } 145 146 /** 147 * Configures the field's quickfinder for a user lookup 148 * 149 * @param view view instance that contains the field 150 * @param field field instance the quickfinder should be associated with 151 */ 152 protected void buildUserQuickfinder(View view, InputField field) { 153 QuickFinder quickFinder = field.getQuickfinder(); 154 155 // if they explicity turned off the quickfinder we will not build it 156 if ((quickFinder != null) && !quickFinder.isRender()) { 157 return; 158 } 159 160 if (quickFinder == null) { 161 quickFinder = ComponentFactory.getQuickFinder(); 162 view.assignComponentIds(quickFinder); 163 164 field.setQuickfinder(quickFinder); 165 } 166 167 if (StringUtils.isBlank(quickFinder.getDataObjectClassName())) { 168 quickFinder.setDataObjectClassName(Person.class.getName()); 169 } 170 171 if (quickFinder.getFieldConversions().isEmpty()) { 172 quickFinder.getFieldConversions().put("principalId", principalIdPropertyName); 173 174 if (StringUtils.isNotBlank(personNamePropertyName)) { 175 quickFinder.getFieldConversions().put("name", personNamePropertyName); 176 } else { 177 quickFinder.getFieldConversions().put("name", personObjectPropertyName + ".name"); 178 } 179 180 quickFinder.getFieldConversions().put("principalName", field.getPropertyName()); 181 } 182 } 183 184 /** 185 * The name of the property on the parent object that holds the principal id 186 * 187 * @return principalIdPropertyName 188 */ 189 @BeanTagAttribute(name="principalIdPropertyName") 190 public String getPrincipalIdPropertyName() { 191 return principalIdPropertyName; 192 } 193 194 /** 195 * Setter for the name of the property on the parent object that holds the principal id 196 * 197 * @param principalIdPropertyName 198 */ 199 public void setPrincipalIdPropertyName(String principalIdPropertyName) { 200 this.principalIdPropertyName = principalIdPropertyName; 201 } 202 203 /** 204 * The name of the property on the parent object that holds the person name 205 * 206 * @return personNamePropertyName 207 */ 208 @BeanTagAttribute(name="personNamePropertyName") 209 public String getPersonNamePropertyName() { 210 return personNamePropertyName; 211 } 212 213 /** 214 * Setter for the name of the property on the parent object that holds the person name 215 * 216 * @param personNamePropertyName 217 */ 218 public void setPersonNamePropertyName(String personNamePropertyName) { 219 this.personNamePropertyName = personNamePropertyName; 220 } 221 222 /** 223 * The name of the property on the parent object that holds the person object 224 * 225 * @return personObjectPropertyName 226 */ 227 @BeanTagAttribute(name="personObjectPropertyName") 228 public String getPersonObjectPropertyName() { 229 return personObjectPropertyName; 230 } 231 232 /** 233 * Setter for the name of the property on the parent object that holds the person object 234 * 235 * @param personObjectPropertyName 236 */ 237 public void setPersonObjectPropertyName(String personObjectPropertyName) { 238 this.personObjectPropertyName = personObjectPropertyName; 239 } 240 241 242 /** 243 * @see org.kuali.rice.krad.uif.component.ComponentBase#copy() 244 */ 245 @Override 246 protected <T> void copyProperties(T component) { 247 super.copyProperties(component); 248 UserControl userControlCopy = (UserControl) component; 249 userControlCopy.setPrincipalIdPropertyName(this.getPrincipalIdPropertyName()); 250 userControlCopy.setPersonNamePropertyName(this.getPersonNamePropertyName()); 251 userControlCopy.setPersonObjectPropertyName(this.getPersonObjectPropertyName()); 252 } 253 }