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 }