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