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 }