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.web.service.impl;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.krad.uif.UifConstants;
20  import org.kuali.rice.krad.uif.UifParameters;
21  import org.kuali.rice.krad.uif.component.MethodInvokerConfig;
22  import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle;
23  import org.kuali.rice.krad.util.GlobalVariables;
24  import org.kuali.rice.krad.util.KRADConstants;
25  import org.kuali.rice.krad.web.form.UifFormBase;
26  import org.kuali.rice.krad.web.service.ModelAndViewService;
27  import org.kuali.rice.krad.web.service.RefreshControllerService;
28  import org.springframework.web.servlet.ModelAndView;
29  import org.springframework.web.servlet.support.RequestContextUtils;
30  
31  import javax.servlet.http.HttpServletRequest;
32  import java.util.Map;
33  
34  /**
35   * Default implementation of the refresh controller service.
36   *
37   * @author Kuali Rice Team (rice.collab@kuali.org)
38   */
39  public class RefreshControllerServiceImpl implements RefreshControllerService {
40  
41      private ModelAndViewService modelAndViewService;
42  
43      /**
44       * Handles the refresh call by checking the request parameters and delegating out to helper methods.
45       *
46       * {@inheritDoc}
47       */
48      @Override
49      public ModelAndView refresh(UifFormBase form) {
50          HttpServletRequest request = form.getRequest();
51  
52          if (request.getParameterMap().containsKey(UifParameters.MESSAGE_TO_DISPLAY)) {
53              String messageToDisplay = request.getParameter(UifParameters.MESSAGE_TO_DISPLAY);
54  
55              if (StringUtils.isNotBlank(messageToDisplay)) {
56                  GlobalVariables.getMessageMap().putErrorForSectionId(KRADConstants.GLOBAL_ERRORS, messageToDisplay);
57              }
58          }
59  
60          if (request.getParameterMap().containsKey(UifParameters.REFRESH_STATUS)) {
61              String refreshStatus = request.getParameter(UifParameters.REFRESH_STATUS);
62  
63              // if the return URL reported an error, do not continue with the refresh call
64              if (UifConstants.RefreshStatus.ERROR.equals(refreshStatus)) {
65                  return getModelAndViewService().getModelAndView(form);
66              }
67          }
68  
69          String refreshCallerType = "";
70          if (request.getParameterMap().containsKey(KRADConstants.REFRESH_CALLER_TYPE)) {
71              refreshCallerType = request.getParameter(KRADConstants.REFRESH_CALLER_TYPE);
72          }
73  
74          if (StringUtils.equals(refreshCallerType, UifConstants.RefreshCallerTypes.MULTI_VALUE_LOOKUP)) {
75              processMultiValueReturn(form, request);
76          }
77  
78          if (request.getParameterMap().containsKey(KRADConstants.REFERENCES_TO_REFRESH)) {
79              final String referencesToRefresh = request.getParameter(KRADConstants.REFERENCES_TO_REFRESH);
80  
81              Runnable runnable = new Runnable() {
82                  @Override
83                  public void run() {
84                      ViewLifecycle.getHelper().refreshReferences(referencesToRefresh);
85                  }
86              };
87  
88              ViewLifecycle.encapsulateLifecycle(form.getView(), form, form.getViewPostMetadata(), null, request,
89                      runnable);
90          }
91  
92          if (request.getParameterMap().containsKey(UifParameters.QUICKFINDER_ID)) {
93              String quickfinderId = request.getParameter(UifParameters.QUICKFINDER_ID);
94  
95              setFocusJumpFromQuickfinder(form, quickfinderId);
96  
97              invokeQuickfinderCallback(form, request, quickfinderId);
98          }
99  
100         return getModelAndViewService().getModelAndView(form);
101     }
102 
103     /**
104      * Handles the return from a multi-value lookup, processing any select line values and invoking the
105      * configured view helper service to create the lines for those values in the model collection.
106      *
107      * <p>There are two supported strategies for returning the selected lines. One, if the lookup view
108      * and the caller are within the same application container, Springs input flash map is used. If however,
109      * the lookup view is outside the caller, then just a standard request parameter is used.</p>
110      *
111      * @param form form instance containing the model data
112      * @param request http request object being handled
113      */
114     protected void processMultiValueReturn(final UifFormBase form, HttpServletRequest request) {
115         final String lookupCollectionId = request.getParameter(UifParameters.LOOKUP_COLLECTION_ID);
116 
117         final String lookupCollectionName = request.getParameter(UifParameters.LOOKUP_COLLECTION_NAME);
118         if (StringUtils.isBlank(lookupCollectionName)) {
119             throw new RuntimeException("Lookup collection name is required for processing multi-value lookup results");
120         }
121 
122         final String multiValueReturnFields = request.getParameter(UifParameters.MULIT_VALUE_RETURN_FILEDS);
123         String selectedLineValuesParam = request.getParameter(UifParameters.SELECTED_LINE_VALUES);
124 
125         String flashMapSelectedLineValues = "";
126         if (RequestContextUtils.getInputFlashMap(request) != null) {
127             flashMapSelectedLineValues = (String) RequestContextUtils.getInputFlashMap(request).get(
128                     UifParameters.SELECTED_LINE_VALUES);
129         }
130 
131         if (!StringUtils.isBlank(flashMapSelectedLineValues)) {
132             selectedLineValuesParam = flashMapSelectedLineValues;
133         }
134 
135         final String selectedLineValues = selectedLineValuesParam;
136 
137         Runnable runnable = new Runnable() {
138             @Override
139             public void run() {
140                 // invoked view helper to populate the collection from lookup results
141                 ViewLifecycle.getHelper().processMultipleValueLookupResults(form, lookupCollectionId,
142                         lookupCollectionName, multiValueReturnFields, selectedLineValues);
143             }
144         };
145 
146         ViewLifecycle.encapsulateLifecycle(form.getView(), form, form.getViewPostMetadata(), null, request, runnable);
147     }
148 
149     /**
150      * Retrieves the configured focus id and jump id for the quickfinder from the post metadata, and sets
151      * those values onto the form for the view rendering.
152      *
153      * @param form form instance containing the model data
154      * @param quickfinderId id for the quickfinder component that triggered the lookup we are
155      * returning from
156      */
157     protected void setFocusJumpFromQuickfinder(UifFormBase form, String quickfinderId) {
158         String focusId = (String) form.getViewPostMetadata().getComponentPostData(quickfinderId,
159                 UifConstants.PostMetadata.QUICKFINDER_FOCUS_ID);
160         if (StringUtils.isNotBlank(focusId)) {
161             form.setFocusId(focusId);
162         }
163 
164         String jumpToId = (String) form.getViewPostMetadata().getComponentPostData(quickfinderId,
165                 UifConstants.PostMetadata.QUICKFINDER_JUMP_TO_ID);
166         if (StringUtils.isNotBlank(jumpToId)) {
167             form.setJumpToId(jumpToId);
168         }
169     }
170 
171     /**
172      * Retrieves post metadata for the quickfinder component with the given id and if a callback method
173      * has been configured, invokes that callback method.
174      *
175      * @param form form instance containing the model data
176      * @param request http request object being handled
177      * @param quickfinderId id for the quickfinder component that triggered the lookup we are
178      * returning from
179      */
180     protected void invokeQuickfinderCallback(UifFormBase form, final HttpServletRequest request,
181             final String quickfinderId) {
182         String callbackMethodToCall = (String) form.getViewPostMetadata().getComponentPostData(quickfinderId,
183                 UifConstants.PostMetadata.QUICKFINDER_CALLBACK_METHOD_TO_CALL);
184         MethodInvokerConfig callbackMethod = (MethodInvokerConfig) form.getViewPostMetadata().
185                 getComponentPostData(quickfinderId, UifConstants.PostMetadata.QUICKFINDER_CALLBACK_METHOD);
186 
187         if (StringUtils.isBlank(callbackMethodToCall) && (callbackMethod == null)) {
188             return;
189         }
190 
191         if (callbackMethod == null) {
192             callbackMethod = new MethodInvokerConfig();
193         }
194 
195         // get additional parameters to be passed to the callback method
196         Map<String, String> callbackContext = (Map<String, String>) form.getViewPostMetadata().
197                 getComponentPostData(quickfinderId, UifConstants.PostMetadata.QUICKFINDER_CALLBACK_CONTEXT);
198 
199         // if target class or object not set, use view helper service
200         if ((callbackMethod.getTargetClass() == null) && (callbackMethod.getTargetObject() == null)) {
201             callbackMethod.setTargetObject(form.getViewHelperService());
202         }
203 
204         callbackMethod.setTargetMethod(callbackMethodToCall);
205 
206         Object[] arguments = new Object[3];
207         arguments[0] = form;
208         arguments[1] = quickfinderId;
209         arguments[2] = callbackContext;
210         callbackMethod.setArguments(arguments);
211 
212         final MethodInvokerConfig methodToInvoke = callbackMethod;
213 
214         Runnable runnable = new Runnable() {
215             @Override
216             public void run() {
217                 try {
218                     methodToInvoke.prepare();
219                     methodToInvoke.invoke();
220                 } catch (Exception e) {
221                     throw new RuntimeException("Error invoking callback method for quickfinder: " + quickfinderId, e);
222                 }
223             }
224         };
225 
226         ViewLifecycle.encapsulateLifecycle(form.getView(), form, form.getViewPostMetadata(), null, request, runnable);
227     }
228 
229     /**
230      * Instance of model and view service to use within the collection service.
231      *
232      * @return ModelAndViewService instance
233      */
234     protected ModelAndViewService getModelAndViewService() {
235         return modelAndViewService;
236     }
237 
238     /**
239      * @see RefreshControllerServiceImpl#getModelAndViewService()
240      */
241     public void setModelAndViewService(ModelAndViewService modelAndViewService) {
242         this.modelAndViewService = modelAndViewService;
243     }
244 }