View Javadoc

1   /**
2    * Copyright 2005-2014 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.widget;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.core.api.CoreApiServiceLocator;
20  import org.kuali.rice.core.web.format.Formatter;
21  import org.kuali.rice.krad.bo.ExternalizableBusinessObject;
22  import org.kuali.rice.krad.service.KRADServiceLocator;
23  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
24  import org.kuali.rice.krad.service.ModuleService;
25  import org.kuali.rice.krad.uif.UifConstants;
26  import org.kuali.rice.krad.uif.UifParameters;
27  import org.kuali.rice.krad.uif.component.BindingInfo;
28  import org.kuali.rice.krad.uif.component.Component;
29  import org.kuali.rice.krad.uif.field.DataField;
30  import org.kuali.rice.krad.uif.field.LinkField;
31  import org.kuali.rice.krad.uif.util.LookupInquiryUtils;
32  import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
33  import org.kuali.rice.krad.uif.util.ViewModelUtils;
34  import org.kuali.rice.krad.uif.view.View;
35  import org.kuali.rice.krad.util.UrlFactory;
36  
37  import java.security.GeneralSecurityException;
38  import java.util.HashMap;
39  import java.util.List;
40  import java.util.Map;
41  import java.util.Map.Entry;
42  import java.util.Properties;
43  
44  /**
45   * Widget for rendering an Inquiry link on a field's value
46   *
47   * @author Kuali Rice Team (rice.collab@kuali.org)
48   */
49  public class Inquiry extends WidgetBase {
50      private static final long serialVersionUID = -2154388007867302901L;
51      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(Inquiry.class);
52  
53      public static final String INQUIRY_TITLE_PREFIX = "title.inquiry.url.value.prependtext";
54  
55      private String baseInquiryUrl;
56  
57      private String dataObjectClassName;
58      private String viewName;
59  
60      private Map<String, String> inquiryParameters;
61  
62      private boolean forceInquiry;
63  
64      private LinkField inquiryLinkField;
65  
66      public Inquiry() {
67          super();
68  
69          forceInquiry = false;
70          inquiryParameters = new HashMap<String, String>();
71      }
72  
73      /**
74       * @see org.kuali.rice.krad.uif.widget.WidgetBase#performFinalize(org.kuali.rice.krad.uif.view.View,
75       *      java.lang.Object, org.kuali.rice.krad.uif.component.Component)
76       */
77      @Override
78      public void performFinalize(View view, Object model, Component parent) {
79          super.performFinalize(view, model, parent);
80  
81          // only set inquiry if enabled
82          if (!isRender() || !isReadOnly()) {
83              return;
84          }
85  
86          // set render to false until we find an inquiry class
87          setRender(false);
88  
89          DataField field = (DataField) parent;
90  
91          // check if field value is null, if so no inquiry
92          Object propertyValue = ObjectPropertyUtils.getPropertyValue(model, field.getBindingInfo().getBindingPath());
93          if ((propertyValue == null) || StringUtils.isBlank(propertyValue.toString())) {
94              return;
95          }
96  
97          setupLink(view, model, field);
98      }
99  
100     /**
101      * Get parent object and field name and build the inquiry link
102      * This was moved from the performFinalize because overlapping and to be used
103      * by DirectInquiry
104      *
105      * @param view - Container View
106      * @param model - model
107      * @param field - The parent Attribute field
108      */
109     public void setupLink(View view, Object model, DataField field) {
110         String propertyName = field.getBindingInfo().getBindingName();
111 
112         // if class and parameters configured, build link from those
113         if (StringUtils.isNotBlank(getDataObjectClassName()) && (getInquiryParameters() != null) &&
114                 !getInquiryParameters().isEmpty()) {
115             Class<?> inquiryObjectClass = null;
116             try {
117                 inquiryObjectClass = Class.forName(getDataObjectClassName());
118             } catch (ClassNotFoundException e) {
119                 LOG.error("Unable to get class for: " + getDataObjectClassName());
120                 throw new RuntimeException(e);
121             }
122 
123             updateInquiryParameters(field.getBindingInfo());
124 
125             buildInquiryLink(model, propertyName, inquiryObjectClass, getInquiryParameters());
126         }
127         // get inquiry class and parameters from view helper
128         else {
129             // get parent object for inquiry metadata
130             Object parentObject = ViewModelUtils.getParentObjectForMetadata(view, model, field);
131             view.getViewHelperService().buildInquiryLink(parentObject, propertyName, this);
132         }
133     }
134 
135     /**
136      * Adjusts the path on the inquiry parameter property to match the binding
137      * path prefix of the given <code>BindingInfo</code>
138      *
139      * @param bindingInfo - binding info instance to copy binding path prefix from
140      */
141     public void updateInquiryParameters(BindingInfo bindingInfo) {
142         Map<String, String> adjustedInquiryParameters = new HashMap<String, String>();
143         for (String fromField : inquiryParameters.keySet()) {
144             String toField = inquiryParameters.get(fromField);
145             String adjustedFromFieldPath = bindingInfo.getPropertyAdjustedBindingPath(fromField);
146 
147             adjustedInquiryParameters.put(adjustedFromFieldPath, toField);
148         }
149 
150         this.inquiryParameters = adjustedInquiryParameters;
151     }
152 
153     /**
154      * Builds the inquiry link based on the given inquiry class and parameters
155      *
156      * @param dataObject - parent object that contains the data (used to pull inquiry
157      * parameters)
158      * @param propertyName - name of the property the inquiry is set on
159      * @param inquiryObjectClass - class of the object the inquiry should point to
160      * @param inquiryParms - map of key field mappings for the inquiry
161      */
162     public void buildInquiryLink(Object dataObject, String propertyName, Class<?> inquiryObjectClass,
163             Map<String, String> inquiryParms) {
164         Properties urlParameters = new Properties();
165 
166         urlParameters.put(UifParameters.DATA_OBJECT_CLASS_NAME, inquiryObjectClass.getName());
167         urlParameters.put(UifParameters.METHOD_TO_CALL, UifConstants.MethodToCallNames.START);
168 
169         for (Entry<String, String> inquiryParameter : inquiryParms.entrySet()) {
170             String parameterName = inquiryParameter.getKey();
171 
172             Object parameterValue = ObjectPropertyUtils.getPropertyValue(dataObject, parameterName);
173 
174             // TODO: need general format util that uses spring
175             if (parameterValue == null) {
176                 parameterValue = "";
177             } else if (parameterValue instanceof java.sql.Date) {
178                 if (Formatter.findFormatter(parameterValue.getClass()) != null) {
179                     Formatter formatter = Formatter.getFormatter(parameterValue.getClass());
180                     parameterValue = formatter.format(parameterValue);
181                 }
182             } else {
183                 parameterValue = parameterValue.toString();
184             }
185 
186             // Encrypt value if it is a field that has restriction that prevents a value from being shown to
187             // user, because we don't want the browser history to store the restricted attributes value in the URL
188             if (KRADServiceLocatorWeb.getDataObjectAuthorizationService()
189                     .attributeValueNeedsToBeEncryptedOnFormsAndLinks(inquiryObjectClass, inquiryParameter.getValue())) {
190                 try {
191                     if(CoreApiServiceLocator.getEncryptionService().isEnabled()) {
192                         parameterValue = CoreApiServiceLocator.getEncryptionService().encrypt(parameterValue);
193                     }
194                 } catch (GeneralSecurityException e) {
195                     LOG.error("Exception while trying to encrypted value for inquiry framework.", e);
196                     throw new RuntimeException(e);
197                 }
198             }
199 
200             // add inquiry parameter to URL
201             urlParameters.put(inquiryParameter.getValue(), parameterValue);
202         }
203 
204         // build inquiry URL
205         String inquiryUrl = "";
206 
207         // check for EBOs for an alternate inquiry URL
208         ModuleService responsibleModuleService =
209                 KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(inquiryObjectClass);
210         if (responsibleModuleService != null && responsibleModuleService.isExternalizable(inquiryObjectClass)) {
211             inquiryUrl = responsibleModuleService.getExternalizableDataObjectLookupUrl(inquiryObjectClass,
212                     urlParameters);
213         } else {
214             inquiryUrl = UrlFactory.parameterizeUrl(getBaseInquiryUrl(), urlParameters);
215         }
216 
217         getInquiryLinkField().setHrefText(inquiryUrl);
218 
219         // set inquiry title
220         String linkTitle = createTitleText(inquiryObjectClass);
221         linkTitle = LookupInquiryUtils.getLinkTitleText(linkTitle, inquiryObjectClass, getInquiryParameters());
222         getInquiryLinkField().setTitle(linkTitle);
223 
224         setRender(true);
225     }
226 
227     /**
228      * Gets text to prepend to the inquiry link title
229      *
230      * @param dataObjectClass - data object class being inquired into
231      * @return String title prepend text
232      */
233     public String createTitleText(Class<?> dataObjectClass) {
234         String titleText = "";
235 
236         String titlePrefixProp =
237                 KRADServiceLocator.getKualiConfigurationService().getPropertyValueAsString(INQUIRY_TITLE_PREFIX);
238         if (StringUtils.isNotBlank(titlePrefixProp)) {
239             titleText += titlePrefixProp + " ";
240         }
241 
242         String objectLabel = KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary()
243                 .getDataObjectEntry(dataObjectClass.getName()).getObjectLabel();
244         if (StringUtils.isNotBlank(objectLabel)) {
245             titleText += objectLabel + " ";
246         }
247 
248         return titleText;
249     }
250 
251     /**
252      * @see org.kuali.rice.krad.uif.component.ComponentBase#getComponentsForLifecycle()
253      */
254     @Override
255     public List<Component> getComponentsForLifecycle() {
256         List<Component> components = super.getComponentsForLifecycle();
257 
258         components.add(getInquiryLinkField());
259 
260         return components;
261     }
262 
263     public String getBaseInquiryUrl() {
264         return this.baseInquiryUrl;
265     }
266 
267     public void setBaseInquiryUrl(String baseInquiryUrl) {
268         this.baseInquiryUrl = baseInquiryUrl;
269     }
270 
271     public String getDataObjectClassName() {
272         return this.dataObjectClassName;
273     }
274 
275     public void setDataObjectClassName(String dataObjectClassName) {
276         this.dataObjectClassName = dataObjectClassName;
277     }
278 
279     public String getViewName() {
280         return this.viewName;
281     }
282 
283     public void setViewName(String viewName) {
284         this.viewName = viewName;
285     }
286 
287     public boolean isForceInquiry() {
288         return this.forceInquiry;
289     }
290 
291     public void setForceInquiry(boolean forceInquiry) {
292         this.forceInquiry = forceInquiry;
293     }
294 
295     public Map<String, String> getInquiryParameters() {
296         return this.inquiryParameters;
297     }
298 
299     public void setInquiryParameters(Map<String, String> inquiryParameters) {
300         this.inquiryParameters = inquiryParameters;
301     }
302 
303     public LinkField getInquiryLinkField() {
304         return this.inquiryLinkField;
305     }
306 
307     public void setInquiryLinkField(LinkField inquiryLinkField) {
308         this.inquiryLinkField = inquiryLinkField;
309     }
310 }