View Javadoc

1   /**
2    * Copyright 2005-2015 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.uif.control;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.kim.api.KimConstants;
20  import org.kuali.rice.kim.api.identity.Person;
21  import org.kuali.rice.kim.api.identity.PersonService;
22  import org.kuali.rice.kim.api.identity.principal.Principal;
23  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
24  import org.kuali.rice.krad.datadictionary.parse.BeanTag;
25  import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
26  import org.kuali.rice.krad.uif.UifConstants;
27  import org.kuali.rice.krad.uif.field.InputField;
28  import org.kuali.rice.krad.uif.util.ComponentFactory;
29  import org.kuali.rice.krad.uif.util.ScriptUtils;
30  import org.kuali.rice.krad.uif.view.View;
31  import org.kuali.rice.krad.uif.component.Component;
32  import org.kuali.rice.krad.uif.component.MethodInvokerConfig;
33  import org.kuali.rice.krad.uif.field.AttributeQuery;
34  import org.kuali.rice.krad.uif.widget.QuickFinder;
35  
36  import java.util.HashMap;
37  import java.util.Map;
38  
39  /**
40   * Represents a user control, which is a special control to handle the input of a Person
41   *
42   * @author Kuali Rice Team (rice.collab@kuali.org)
43   */
44  @BeanTag(name = "kimPersonControl-bean", parent = "Uif-KimPersonControl")
45  public class UserControl extends TextControl implements FilterableLookupCriteriaControl {
46      private static final long serialVersionUID = 7468340793076585869L;
47  
48      private String principalIdPropertyName;
49      private String personNamePropertyName;
50      private String personObjectPropertyName;
51  
52      public UserControl() {
53          super();
54      }
55  
56      /**
57       * @see org.kuali.rice.krad.uif.component.ComponentBase#performApplyModel(org.kuali.rice.krad.uif.view.View,
58       *      java.lang.Object, org.kuali.rice.krad.uif.component.Component)
59       */
60      @Override
61      public void performApplyModel(View view, Object model, Component parent) {
62          super.performApplyModel(view, model, parent);
63  
64          if (!(parent instanceof InputField)) {
65              return;
66          }
67  
68          InputField field = (InputField) parent;
69          field.getAdditionalHiddenPropertyNames().add(principalIdPropertyName);
70  
71          if (!field.isReadOnly()) {
72              // add information fields
73              if (StringUtils.isNotBlank(personNamePropertyName)) {
74                  field.getPropertyNamesForAdditionalDisplay().add(personNamePropertyName);
75              } else {
76                  field.getPropertyNamesForAdditionalDisplay().add(
77                          personObjectPropertyName + "." + KimConstants.AttributeConstants.NAME);
78              }
79  
80              // setup script to clear id field when name is modified
81              String idPropertyPath = field.getBindingInfo().getPropertyAdjustedBindingPath(principalIdPropertyName);
82              String onChangeScript = UifConstants.JsFunctions.SET_VALUE
83                      + "('"
84                      + ScriptUtils.escapeName(idPropertyPath)
85                      + "','');";
86  
87              if (StringUtils.isNotBlank(getOnChangeScript())) {
88                  onChangeScript = getOnChangeScript() + onChangeScript;
89              }
90              setOnChangeScript(onChangeScript);
91          }
92  
93          if (field.isReadOnly() && StringUtils.isBlank(field.getReadOnlyDisplaySuffixPropertyName())) {
94              if (StringUtils.isNotBlank(personNamePropertyName)) {
95                  field.setReadOnlyDisplaySuffixPropertyName(personNamePropertyName);
96              } else {
97                  field.setReadOnlyDisplaySuffixPropertyName(
98                          personObjectPropertyName + "." + KimConstants.AttributeConstants.NAME);
99              }
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 }