Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
UifFormBase |
|
| 1.2321428571428572;1.232 |
1 | /** | |
2 | * Copyright 2005-2011 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.form; | |
17 | ||
18 | import org.apache.commons.lang.StringUtils; | |
19 | import org.codehaus.jackson.map.ObjectMapper; | |
20 | import org.kuali.rice.krad.service.KRADServiceLocatorWeb; | |
21 | import org.kuali.rice.krad.uif.UifConstants; | |
22 | import org.kuali.rice.krad.uif.UifParameters; | |
23 | import org.kuali.rice.krad.uif.view.History; | |
24 | import org.kuali.rice.krad.uif.view.View; | |
25 | import org.kuali.rice.krad.uif.service.ViewService; | |
26 | import org.kuali.rice.krad.uif.view.ViewModel; | |
27 | import org.kuali.rice.krad.util.KRADUtils; | |
28 | import org.springframework.web.multipart.MultipartFile; | |
29 | import org.kuali.rice.krad.uif.UifConstants.ViewType; | |
30 | ||
31 | import javax.servlet.http.HttpServletRequest; | |
32 | import java.io.IOException; | |
33 | import java.util.ArrayList; | |
34 | import java.util.HashMap; | |
35 | import java.util.List; | |
36 | import java.util.Map; | |
37 | import java.util.Properties; | |
38 | import java.util.Set; | |
39 | import java.util.UUID; | |
40 | ||
41 | /** | |
42 | * Base form class for views within the KRAD User Interface Framework | |
43 | * | |
44 | * <p> | |
45 | * Holds properties necessary to determine the <code>View</code> instance that | |
46 | * will be used to render the UI | |
47 | * </p> | |
48 | * | |
49 | * @author Kuali Rice Team (rice.collab@kuali.org) | |
50 | */ | |
51 | public class UifFormBase implements ViewModel { | |
52 | private static final long serialVersionUID = 8432543267099454434L; | |
53 | ||
54 | // current view | |
55 | protected String viewId; | |
56 | protected String viewName; | |
57 | protected ViewType viewTypeName; | |
58 | protected String pageId; | |
59 | protected String methodToCall; | |
60 | protected String formKey; | |
61 | protected String jumpToId; | |
62 | protected String jumpToName; | |
63 | protected String focusId; | |
64 | protected String formPostUrl; | |
65 | ||
66 | protected boolean defaultsApplied; | |
67 | ||
68 | protected View view; | |
69 | protected View previousView; | |
70 | ||
71 | protected Map<String, String> viewRequestParameters; | |
72 | protected List<String> readOnlyFieldsList; | |
73 | ||
74 | protected Map<String, Object> newCollectionLines; | |
75 | protected Map<String, String> actionParameters; | |
76 | protected Map<String, Object> clientStateForSyncing; | |
77 | protected Map<String, Set<String>> selectedCollectionLines; | |
78 | ||
79 | protected MultipartFile attachmentFile; | |
80 | ||
81 | // navigation | |
82 | protected String returnLocation; | |
83 | protected String returnFormKey; | |
84 | ||
85 | protected History formHistory; | |
86 | ||
87 | protected boolean renderFullView; | |
88 | protected boolean validateDirty; | |
89 | ||
90 | 0 | public UifFormBase() { |
91 | 0 | formKey = generateFormKey(); |
92 | 0 | renderFullView = true; |
93 | 0 | defaultsApplied = false; |
94 | ||
95 | 0 | readOnlyFieldsList = new ArrayList<String>(); |
96 | 0 | viewRequestParameters = new HashMap<String, String>(); |
97 | 0 | newCollectionLines = new HashMap<String, Object>(); |
98 | 0 | actionParameters = new HashMap<String, String>(); |
99 | 0 | clientStateForSyncing = new HashMap<String, Object>(); |
100 | 0 | selectedCollectionLines = new HashMap<String, Set<String>>(); |
101 | 0 | } |
102 | ||
103 | /** | |
104 | * Creates the unique id used to store this "conversation" in the session. | |
105 | * The default method generates a java UUID. | |
106 | * | |
107 | * @return | |
108 | */ | |
109 | protected String generateFormKey() { | |
110 | 0 | return UUID.randomUUID().toString(); |
111 | } | |
112 | ||
113 | /** | |
114 | * Called after Spring binds the request to the form and before the | |
115 | * controller method is invoked. | |
116 | * | |
117 | * @param request - request object containing the query parameters | |
118 | */ | |
119 | public void postBind(HttpServletRequest request) { | |
120 | // default form post URL to request URL | |
121 | 0 | formPostUrl = request.getRequestURL().toString(); |
122 | ||
123 | // get any sent client view state and parse into map | |
124 | 0 | if (request.getParameterMap().containsKey(UifParameters.CLIENT_VIEW_STATE)) { |
125 | 0 | String clientStateJSON = request.getParameter(UifParameters.CLIENT_VIEW_STATE); |
126 | 0 | if (StringUtils.isNotBlank(clientStateJSON)) { |
127 | // change single quotes to double quotes (necessary because the reverse was done for sending) | |
128 | 0 | clientStateJSON = StringUtils.replace(clientStateJSON, "'", "\""); |
129 | ||
130 | 0 | ObjectMapper mapper = new ObjectMapper(); |
131 | try { | |
132 | 0 | clientStateForSyncing = mapper.readValue(clientStateJSON, Map.class); |
133 | 0 | } catch (IOException e) { |
134 | 0 | throw new RuntimeException("Unable to decode client side state JSON", e); |
135 | 0 | } |
136 | } | |
137 | } | |
138 | ||
139 | // populate read only fields list | |
140 | 0 | if (request.getParameter(UifParameters.READ_ONLY_FIELDS) != null) { |
141 | 0 | String readOnlyFields = request.getParameter(UifParameters.READ_ONLY_FIELDS); |
142 | 0 | setReadOnlyFieldsList(KRADUtils.convertStringParameterToList(readOnlyFields)); |
143 | } | |
144 | 0 | } |
145 | ||
146 | /** | |
147 | * @see org.kuali.rice.krad.uif.view.ViewModel#getViewId() | |
148 | */ | |
149 | public String getViewId() { | |
150 | 0 | return this.viewId; |
151 | } | |
152 | ||
153 | /** | |
154 | * @see org.kuali.rice.krad.uif.view.ViewModel#setViewId(java.lang.String) | |
155 | */ | |
156 | public void setViewId(String viewId) { | |
157 | 0 | this.viewId = viewId; |
158 | 0 | } |
159 | ||
160 | /** | |
161 | * @see org.kuali.rice.krad.uif.view.ViewModel#getViewName() | |
162 | */ | |
163 | public String getViewName() { | |
164 | 0 | return this.viewName; |
165 | } | |
166 | ||
167 | /** | |
168 | * @see org.kuali.rice.krad.uif.view.ViewModel#setViewName(java.lang.String) | |
169 | */ | |
170 | public void setViewName(String viewName) { | |
171 | 0 | this.viewName = viewName; |
172 | 0 | } |
173 | ||
174 | /** | |
175 | * @see org.kuali.rice.krad.uif.view.ViewModel#getViewTypeName() | |
176 | */ | |
177 | public ViewType getViewTypeName() { | |
178 | 0 | return this.viewTypeName; |
179 | } | |
180 | ||
181 | /** | |
182 | * @see org.kuali.rice.krad.uif.view.ViewModel#setViewTypeName(org.kuali.rice.krad.uif.UifConstants.ViewType) | |
183 | */ | |
184 | public void setViewTypeName(ViewType viewTypeName) { | |
185 | 0 | this.viewTypeName = viewTypeName; |
186 | 0 | } |
187 | ||
188 | /** | |
189 | * @see org.kuali.rice.krad.uif.view.ViewModel#getPageId() | |
190 | */ | |
191 | public String getPageId() { | |
192 | 0 | return this.pageId; |
193 | } | |
194 | ||
195 | /** | |
196 | * @see org.kuali.rice.krad.uif.view.ViewModel#setPageId(java.lang.String) | |
197 | */ | |
198 | public void setPageId(String pageId) { | |
199 | 0 | this.pageId = pageId; |
200 | 0 | } |
201 | ||
202 | /** | |
203 | * @see org.kuali.rice.krad.uif.view.ViewModel#getFormPostUrl() | |
204 | */ | |
205 | public String getFormPostUrl() { | |
206 | 0 | return this.formPostUrl; |
207 | } | |
208 | ||
209 | /** | |
210 | * @see org.kuali.rice.krad.uif.view.ViewModel#setFormPostUrl(java.lang.String) | |
211 | */ | |
212 | public void setFormPostUrl(String formPostUrl) { | |
213 | 0 | this.formPostUrl = formPostUrl; |
214 | 0 | } |
215 | ||
216 | public String getReturnLocation() { | |
217 | 0 | return this.returnLocation; |
218 | } | |
219 | ||
220 | public void setReturnLocation(String returnLocation) { | |
221 | 0 | this.returnLocation = returnLocation; |
222 | 0 | } |
223 | ||
224 | public String getReturnFormKey() { | |
225 | 0 | return this.returnFormKey; |
226 | } | |
227 | ||
228 | public void setReturnFormKey(String returnFormKey) { | |
229 | 0 | this.returnFormKey = returnFormKey; |
230 | 0 | } |
231 | ||
232 | /** | |
233 | * Identifies the controller method that should be invoked to fulfill a | |
234 | * request. The value will be matched up against the 'params' setting on the | |
235 | * <code>RequestMapping</code> annotation for the controller method | |
236 | * | |
237 | * @return String method to call | |
238 | */ | |
239 | public String getMethodToCall() { | |
240 | 0 | return this.methodToCall; |
241 | } | |
242 | ||
243 | /** | |
244 | * Setter for the method to call | |
245 | * | |
246 | * @param methodToCall | |
247 | */ | |
248 | public void setMethodToCall(String methodToCall) { | |
249 | 0 | this.methodToCall = methodToCall; |
250 | 0 | } |
251 | ||
252 | /** | |
253 | * @see org.kuali.rice.krad.uif.view.ViewModel#getViewRequestParameters() | |
254 | */ | |
255 | public Map<String, String> getViewRequestParameters() { | |
256 | 0 | return this.viewRequestParameters; |
257 | } | |
258 | ||
259 | /** | |
260 | * @see org.kuali.rice.krad.uif.view.ViewModel#setViewRequestParameters(java.util.Map<java.lang.String,java.lang.String>) | |
261 | */ | |
262 | public void setViewRequestParameters(Map<String, String> viewRequestParameters) { | |
263 | 0 | this.viewRequestParameters = viewRequestParameters; |
264 | 0 | } |
265 | ||
266 | /** | |
267 | * @see org.kuali.rice.krad.uif.view.ViewModel#getReadOnlyFieldsList() | |
268 | */ | |
269 | public List<String> getReadOnlyFieldsList() { | |
270 | 0 | return readOnlyFieldsList; |
271 | } | |
272 | ||
273 | /** | |
274 | * @see org.kuali.rice.krad.uif.view.ViewModel#setReadOnlyFieldsList(java.util.List<java.lang.String>) | |
275 | */ | |
276 | public void setReadOnlyFieldsList(List<String> readOnlyFieldsList) { | |
277 | 0 | this.readOnlyFieldsList = readOnlyFieldsList; |
278 | 0 | } |
279 | ||
280 | /** | |
281 | * @see org.kuali.rice.krad.uif.view.ViewModel#getNewCollectionLines() | |
282 | */ | |
283 | public Map<String, Object> getNewCollectionLines() { | |
284 | 0 | return this.newCollectionLines; |
285 | } | |
286 | ||
287 | /** | |
288 | * @see org.kuali.rice.krad.uif.view.ViewModel#setNewCollectionLines(java.util.Map<java.lang.String,java.lang.Object>) | |
289 | */ | |
290 | public void setNewCollectionLines(Map<String, Object> newCollectionLines) { | |
291 | 0 | this.newCollectionLines = newCollectionLines; |
292 | 0 | } |
293 | ||
294 | /** | |
295 | * @see org.kuali.rice.krad.uif.view.ViewModel#getActionParameters() | |
296 | */ | |
297 | public Map<String, String> getActionParameters() { | |
298 | 0 | return this.actionParameters; |
299 | } | |
300 | ||
301 | /** | |
302 | * Returns the action parameters map as a <code>Properties</code> instance | |
303 | * | |
304 | * @return Properties action parameters | |
305 | */ | |
306 | public Properties getActionParametersAsProperties() { | |
307 | 0 | Properties actionProperties = new Properties(); |
308 | ||
309 | 0 | if (actionParameters != null) { |
310 | 0 | for (Map.Entry<String, String> actionParameter : actionParameters.entrySet()) { |
311 | 0 | actionProperties.put(actionParameter.getKey(), actionParameter.getValue()); |
312 | } | |
313 | } | |
314 | ||
315 | 0 | return actionProperties; |
316 | } | |
317 | ||
318 | /** | |
319 | * @see org.kuali.rice.krad.uif.view.ViewModel#setActionParameters(java.util.Map<java.lang.String,java.lang.String>) | |
320 | */ | |
321 | public void setActionParameters(Map<String, String> actionParameters) { | |
322 | 0 | this.actionParameters = actionParameters; |
323 | 0 | } |
324 | ||
325 | /** | |
326 | * Retrieves the value for the given action parameter, or empty string if | |
327 | * not found | |
328 | * | |
329 | * @param actionParameterName - name of the action parameter to retrieve value for | |
330 | * @return String parameter value or empty string | |
331 | */ | |
332 | public String getActionParamaterValue(String actionParameterName) { | |
333 | 0 | if ((actionParameters != null) && actionParameters.containsKey(actionParameterName)) { |
334 | 0 | return actionParameters.get(actionParameterName); |
335 | } | |
336 | ||
337 | 0 | return ""; |
338 | } | |
339 | ||
340 | /** | |
341 | * Returns the action event that was sent in the action parameters (if any) | |
342 | * | |
343 | * <p> | |
344 | * The action event is a special action parameter that can be sent to indicate a type of action being taken. This | |
345 | * can be looked at by the view or components to render differently | |
346 | * </p> | |
347 | * | |
348 | * TODO: make sure action parameters are getting reinitialized on each request | |
349 | * | |
350 | * @return String action event name or blank if action event was not sent | |
351 | */ | |
352 | public String getActionEvent() { | |
353 | 0 | if ((actionParameters != null) && actionParameters.containsKey(UifConstants.UrlParams.ACTION_EVENT)) { |
354 | 0 | return actionParameters.get(UifConstants.UrlParams.ACTION_EVENT); |
355 | } | |
356 | ||
357 | 0 | return ""; |
358 | } | |
359 | ||
360 | /** | |
361 | * @see org.kuali.rice.krad.uif.view.ViewModel#getClientStateForSyncing() | |
362 | */ | |
363 | public Map<String, Object> getClientStateForSyncing() { | |
364 | 0 | return clientStateForSyncing; |
365 | } | |
366 | ||
367 | /** | |
368 | * @see org.kuali.rice.krad.uif.view.ViewModel#getSelectedCollectionLines() | |
369 | */ | |
370 | public Map<String, Set<String>> getSelectedCollectionLines() { | |
371 | 0 | return selectedCollectionLines; |
372 | } | |
373 | ||
374 | /** | |
375 | * @see org.kuali.rice.krad.uif.view.ViewModel#setSelectedCollectionLines(java.util.Map<java.lang.String,java.util.Set<java.lang.String>>) | |
376 | */ | |
377 | public void setSelectedCollectionLines(Map<String, Set<String>> selectedCollectionLines) { | |
378 | 0 | this.selectedCollectionLines = selectedCollectionLines; |
379 | 0 | } |
380 | ||
381 | /** | |
382 | * Key string that identifies the form instance in session storage | |
383 | * | |
384 | * <p> | |
385 | * When the view is posted, the previous form instance is retrieved and then | |
386 | * populated from the request parameters. This key string is retrieve the | |
387 | * session form from the session service | |
388 | * </p> | |
389 | * | |
390 | * @return String form session key | |
391 | */ | |
392 | public String getFormKey() { | |
393 | 0 | return this.formKey; |
394 | } | |
395 | ||
396 | /** | |
397 | * Setter for the form's session key | |
398 | * | |
399 | * @param formKey | |
400 | */ | |
401 | public void setFormKey(String formKey) { | |
402 | 0 | this.formKey = formKey; |
403 | 0 | } |
404 | ||
405 | /** | |
406 | * @see org.kuali.rice.krad.uif.view.ViewModel#isDefaultsApplied() | |
407 | */ | |
408 | public boolean isDefaultsApplied() { | |
409 | 0 | return this.defaultsApplied; |
410 | } | |
411 | ||
412 | /** | |
413 | * @see org.kuali.rice.krad.uif.view.ViewModel#setDefaultsApplied(boolean) | |
414 | */ | |
415 | public void setDefaultsApplied(boolean defaultsApplied) { | |
416 | 0 | this.defaultsApplied = defaultsApplied; |
417 | 0 | } |
418 | ||
419 | /** | |
420 | * Holder for files that are attached through the view | |
421 | * | |
422 | * @return MultipartFile representing the attachment | |
423 | */ | |
424 | public MultipartFile getAttachmentFile() { | |
425 | 0 | return this.attachmentFile; |
426 | } | |
427 | ||
428 | /** | |
429 | * Setter for the form's attachment file | |
430 | * | |
431 | * @param attachmentFile | |
432 | */ | |
433 | public void setAttachmentFile(MultipartFile attachmentFile) { | |
434 | 0 | this.attachmentFile = attachmentFile; |
435 | 0 | } |
436 | ||
437 | /** | |
438 | * @return the renderFullView | |
439 | */ | |
440 | public boolean isRenderFullView() { | |
441 | 0 | return this.renderFullView; |
442 | } | |
443 | ||
444 | /** | |
445 | * @param renderFullView | |
446 | */ | |
447 | public void setRenderFullView(boolean renderFullView) { | |
448 | 0 | this.renderFullView = renderFullView; |
449 | 0 | } |
450 | ||
451 | /** | |
452 | * View instance associated with the form. Used to render the user interface | |
453 | * | |
454 | * @return View | |
455 | */ | |
456 | public View getView() { | |
457 | 0 | return this.view; |
458 | } | |
459 | ||
460 | /** | |
461 | * Setter for the view instance | |
462 | * | |
463 | * @param view | |
464 | */ | |
465 | public void setView(View view) { | |
466 | 0 | this.view = view; |
467 | 0 | } |
468 | ||
469 | /** | |
470 | * View instance for the page that made a request. Since a new view instance | |
471 | * gets initialized for each request before the controller logic is invoked, | |
472 | * any state about the previous view is lost. This could be needed to read | |
473 | * metadata from the view for such things as collection processing. When | |
474 | * this is necessary the previous view instance can be retrieved | |
475 | * | |
476 | * @return View instance | |
477 | */ | |
478 | public View getPreviousView() { | |
479 | 0 | return this.previousView; |
480 | } | |
481 | ||
482 | /** | |
483 | * Setter for the previous view instance | |
484 | * | |
485 | * @param previousView | |
486 | */ | |
487 | public void setPreviousView(View previousView) { | |
488 | 0 | this.previousView = previousView; |
489 | 0 | } |
490 | ||
491 | /** | |
492 | * Instance of the <code>ViewService</code> that can be used to retrieve | |
493 | * <code>View</code> instances | |
494 | * | |
495 | * @return ViewService implementation | |
496 | */ | |
497 | protected ViewService getViewService() { | |
498 | 0 | return KRADServiceLocatorWeb.getViewService(); |
499 | } | |
500 | ||
501 | /** | |
502 | * The jumpToId for this form, the element with this id will be jumped to automatically | |
503 | * when the form is loaded in the view. | |
504 | * Using "TOP" or "BOTTOM" will jump to the top or the bottom of the resulting page. | |
505 | * jumpToId always takes precedence over jumpToName, if set. | |
506 | * | |
507 | * @return the jumpToId | |
508 | */ | |
509 | public String getJumpToId() { | |
510 | 0 | return this.jumpToId; |
511 | } | |
512 | ||
513 | /** | |
514 | * @param jumpToId the jumpToId to set | |
515 | */ | |
516 | public void setJumpToId(String jumpToId) { | |
517 | 0 | this.jumpToId = jumpToId; |
518 | 0 | } |
519 | ||
520 | /** | |
521 | * The jumpToName for this form, the element with this name will be jumped to automatically | |
522 | * when the form is loaded in the view. | |
523 | * WARNING: jumpToId always takes precedence over jumpToName, if set. | |
524 | * | |
525 | * @return the jumpToName | |
526 | */ | |
527 | public String getJumpToName() { | |
528 | 0 | return this.jumpToName; |
529 | } | |
530 | ||
531 | /** | |
532 | * @param jumpToName the jumpToName to set | |
533 | */ | |
534 | public void setJumpToName(String jumpToName) { | |
535 | 0 | this.jumpToName = jumpToName; |
536 | 0 | } |
537 | ||
538 | /** | |
539 | * Field to place focus on when the page loads | |
540 | * An empty focusId will result in focusing on the first visible input element by default. | |
541 | * | |
542 | * @return the focusId | |
543 | */ | |
544 | public String getFocusId() { | |
545 | 0 | return this.focusId; |
546 | } | |
547 | ||
548 | /** | |
549 | * @param focusId the focusId to set | |
550 | */ | |
551 | public void setFocusId(String focusId) { | |
552 | 0 | this.focusId = focusId; |
553 | 0 | } |
554 | ||
555 | /** | |
556 | * History parameter representing the History of views that have come before the | |
557 | * viewing of the current view | |
558 | * | |
559 | * <p> | |
560 | * Used for breadcrumb widget generation on the view and also for navigating back | |
561 | * to previous or hub locations | |
562 | * </p> | |
563 | * | |
564 | * @return History instance giving current history | |
565 | */ | |
566 | public History getFormHistory() { | |
567 | 0 | return formHistory; |
568 | } | |
569 | ||
570 | /** | |
571 | * Setter for the current History object | |
572 | * | |
573 | * @param history the history to set | |
574 | */ | |
575 | public void setFormHistory(History history) { | |
576 | 0 | this.formHistory = history; |
577 | 0 | } |
578 | ||
579 | /** | |
580 | * Indicates whether the form should be validated for dirtyness | |
581 | * | |
582 | * <p> | |
583 | * For FormView, it's necessary to validate when the user tries to navigate out of the form. If set, all the | |
584 | * InputFields will be validated on refresh, navigate, cancel or close Action or on form | |
585 | * unload and if dirty, displays a message and user can decide whether to continue with | |
586 | * the action or stay on the form | |
587 | * </p> | |
588 | * | |
589 | * @return boolean true if dirty validation should be enabled | |
590 | */ | |
591 | public boolean isValidateDirty() { | |
592 | 0 | return this.validateDirty; |
593 | } | |
594 | ||
595 | /** | |
596 | * Setter for dirty validation indicator | |
597 | * | |
598 | * @param validateDirty | |
599 | */ | |
600 | public void setValidateDirty(boolean validateDirty) { | |
601 | 0 | this.validateDirty = validateDirty; |
602 | 0 | } |
603 | ||
604 | } |