001/** 002 * Copyright 2005-2015 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 */ 016package org.kuali.rice.krad.web.form; 017 018import org.apache.commons.lang.StringUtils; 019import org.codehaus.jackson.map.ObjectMapper; 020import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 021import org.kuali.rice.krad.uif.UifConstants; 022import org.kuali.rice.krad.uif.UifConstants.ViewType; 023import org.kuali.rice.krad.uif.UifParameters; 024import org.kuali.rice.krad.uif.UifPropertyPaths; 025import org.kuali.rice.krad.uif.component.Component; 026import org.kuali.rice.krad.uif.lifecycle.ViewPostMetadata; 027import org.kuali.rice.krad.uif.service.ViewHelperService; 028import org.kuali.rice.krad.uif.service.ViewService; 029import org.kuali.rice.krad.uif.util.SessionTransient; 030import org.kuali.rice.krad.uif.view.View; 031import org.kuali.rice.krad.uif.view.ViewModel; 032import org.kuali.rice.krad.util.KRADUtils; 033import org.kuali.rice.krad.web.bind.RequestAccessible; 034import org.springframework.web.multipart.MultipartFile; 035 036import javax.servlet.http.HttpServletRequest; 037import java.io.IOException; 038import java.util.ArrayList; 039import java.util.Enumeration; 040import java.util.HashMap; 041import java.util.HashSet; 042import java.util.List; 043import java.util.Map; 044import java.util.Properties; 045import java.util.Set; 046import java.util.UUID; 047 048/** 049 * Base form class for views within the KRAD User Interface Framework. 050 * 051 * <p>Holds properties necessary to determine the {@link org.kuali.rice.krad.uif.view.View} instance that 052 * will be used to render the user interface</p> 053 * 054 * @author Kuali Rice Team (rice.collab@kuali.org) 055 */ 056public class UifFormBase implements ViewModel { 057 058 private static final long serialVersionUID = 8432543267099454434L; 059 060 @RequestAccessible 061 protected String viewId; 062 063 @RequestAccessible 064 protected String viewName; 065 066 @RequestAccessible 067 protected ViewType viewTypeName; 068 069 @RequestAccessible 070 protected String pageId; 071 072 @RequestAccessible 073 protected String methodToCall; 074 075 @RequestAccessible 076 protected String formKey; 077 078 @RequestAccessible 079 @SessionTransient 080 protected String requestedFormKey; 081 082 @RequestAccessible 083 protected String flowKey; 084 085 protected String sessionId; 086 protected int sessionTimeoutInterval; 087 088 @SessionTransient 089 protected HistoryFlow historyFlow; 090 @SessionTransient 091 protected HistoryManager historyManager; 092 093 @RequestAccessible 094 @SessionTransient 095 protected String jumpToId; 096 097 @SessionTransient 098 protected String jumpToName; 099 100 @RequestAccessible 101 @SessionTransient 102 protected String focusId; 103 104 @RequestAccessible 105 @SessionTransient 106 protected boolean dirtyForm; 107 108 protected String formPostUrl; 109 protected String controllerMapping; 110 111 @SessionTransient 112 private String requestUrl; 113 private Map<String, String[]> initialRequestParameters; 114 115 protected String state; 116 117 @RequestAccessible 118 protected boolean renderedInDialog; 119 120 @RequestAccessible 121 protected boolean renderedInIframe; 122 123 @SessionTransient 124 protected String growlScript; 125 126 @SessionTransient 127 protected View view; 128 protected ViewPostMetadata viewPostMetadata; 129 130 protected Map<String, String> viewRequestParameters; 131 protected List<String> readOnlyFieldsList; 132 133 protected Map<String, Object> newCollectionLines; 134 135 @RequestAccessible 136 @SessionTransient 137 protected String triggerActionId; 138 139 @RequestAccessible 140 @SessionTransient 141 protected Map<String, String> actionParameters; 142 143 protected Map<String, Object> clientStateForSyncing; 144 145 @SessionTransient 146 protected Map<String, Set<String>> selectedCollectionLines; 147 148 protected Set<String> selectedLookupResultsCache; 149 150 protected List<Object> addedCollectionItems; 151 152 @SessionTransient 153 protected MultipartFile attachmentFile; 154 155 // navigation 156 @RequestAccessible 157 protected String returnLocation; 158 159 @RequestAccessible 160 protected String returnFormKey; 161 162 @RequestAccessible 163 @SessionTransient 164 protected boolean ajaxRequest; 165 166 @RequestAccessible 167 @SessionTransient 168 protected String ajaxReturnType; 169 170 @SessionTransient 171 private String requestJsonTemplate; 172 @SessionTransient 173 private boolean collectionPagingRequest; 174 175 // dialog fields 176 @RequestAccessible 177 @SessionTransient 178 protected String showDialogId; 179 180 @RequestAccessible 181 @SessionTransient 182 protected String returnDialogId; 183 184 @RequestAccessible 185 @SessionTransient 186 protected String returnDialogResponse; 187 188 @RequestAccessible 189 protected Map<String, String> dialogExplanations; 190 protected Map<String, DialogResponse> dialogResponses; 191 192 @SessionTransient 193 protected boolean requestRedirected; 194 195 @RequestAccessible 196 @SessionTransient 197 protected String updateComponentId; 198 @SessionTransient 199 private Component updateComponent; 200 201 @RequestAccessible 202 protected Map<String, Object> extensionData; 203 204 protected boolean applyDefaultValues; 205 206 protected boolean evaluateFlagsAndModes; 207 protected Boolean canEditView; 208 protected Map<String, Boolean> actionFlags; 209 protected Map<String, Boolean> editModes; 210 211 protected HttpServletRequest request; 212 213 private Object dialogDataObject; 214 215 public UifFormBase() { 216 renderedInDialog = false; 217 renderedInIframe = false; 218 requestRedirected = false; 219 220 readOnlyFieldsList = new ArrayList<String>(); 221 viewRequestParameters = new HashMap<String, String>(); 222 newCollectionLines = new HashMap<String, Object>(); 223 actionParameters = new HashMap<String, String>(); 224 clientStateForSyncing = new HashMap<String, Object>(); 225 selectedCollectionLines = new HashMap<String, Set<String>>(); 226 selectedLookupResultsCache = new HashSet<String>(); 227 addedCollectionItems = new ArrayList<Object>(); 228 dialogExplanations = new HashMap<String, String>(); 229 dialogResponses = new HashMap<String, DialogResponse>(); 230 extensionData = new HashMap<String, Object>(); 231 232 applyDefaultValues = true; 233 evaluateFlagsAndModes = true; 234 } 235 236 /** 237 * {@inheritDoc} 238 */ 239 @Override 240 public void preBind(HttpServletRequest request) { 241 String formKeyParam = request.getParameter(UifParameters.FORM_KEY); 242 if (StringUtils.isNotBlank(formKeyParam)) { 243 UifFormManager uifFormManager = (UifFormManager) request.getSession().getAttribute( 244 UifParameters.FORM_MANAGER); 245 246 // retrieves the session form and updates the request from with the session transient attributes 247 uifFormManager.updateFormWithSession(this, formKeyParam); 248 } 249 250 String requestedFormKey = request.getParameter(UifParameters.REQUESTED_FORM_KEY); 251 if (StringUtils.isNotBlank(requestedFormKey)) { 252 setRequestedFormKey(requestedFormKey); 253 } else { 254 setRequestedFormKey(formKeyParam); 255 } 256 257 this.request = request; 258 } 259 260 /** 261 * {@inheritDoc} 262 */ 263 @Override 264 public void postBind(HttpServletRequest request) { 265 // assign form key if this is a new form or the requested form key is not in session 266 UifFormManager uifFormManager = (UifFormManager) request.getSession().getAttribute(UifParameters.FORM_MANAGER); 267 if (StringUtils.isBlank(formKey) || !uifFormManager.hasSessionForm(formKey)) { 268 formKey = generateFormKey(); 269 } 270 271 // default form post URL to request URL 272 formPostUrl = request.getRequestURL().toString(); 273 274 controllerMapping = request.getPathInfo(); 275 276 if (request.getSession() != null) { 277 sessionId = request.getSession().getId(); 278 sessionTimeoutInterval = request.getSession().getMaxInactiveInterval(); 279 } 280 281 // get any sent client view state and parse into map 282 if (request.getParameterMap().containsKey(UifParameters.CLIENT_VIEW_STATE)) { 283 String clientStateJSON = request.getParameter(UifParameters.CLIENT_VIEW_STATE); 284 if (StringUtils.isNotBlank(clientStateJSON)) { 285 // change single quotes to double quotes (necessary because the reverse was done for sending) 286 clientStateJSON = StringUtils.replace(clientStateJSON, "\\'", "\""); 287 clientStateJSON = StringUtils.replace(clientStateJSON, "\\[", "["); 288 clientStateJSON = StringUtils.replace(clientStateJSON, "\\]", "]"); 289 clientStateJSON = StringUtils.replace(clientStateJSON, "'", "\""); 290 291 ObjectMapper mapper = new ObjectMapper(); 292 try { 293 clientStateForSyncing = mapper.readValue(clientStateJSON, Map.class); 294 } catch (IOException e) { 295 throw new RuntimeException("Unable to decode client side state JSON: " + clientStateJSON, e); 296 } 297 } 298 } 299 300 String requestUrl = KRADUtils.stripXSSPatterns(KRADUtils.getFullURL(request)); 301 setRequestUrl(requestUrl); 302 303 String referer = request.getHeader(UifConstants.REFERER); 304 if (StringUtils.isBlank(referer) && StringUtils.isBlank(getReturnLocation())) { 305 setReturnLocation(UifConstants.NO_RETURN); 306 } else if (StringUtils.isBlank(getReturnLocation())) { 307 setReturnLocation(referer); 308 } 309 310 if (getInitialRequestParameters() == null) { 311 Map<String, String[]> requestParams = new HashMap<String, String[]>(); 312 Enumeration<String> names = request.getParameterNames(); 313 314 while (names != null && names.hasMoreElements()) { 315 String name = KRADUtils.stripXSSPatterns(names.nextElement()); 316 String[] values = KRADUtils.stripXSSPatterns(request.getParameterValues(name)); 317 318 requestParams.put(name, values); 319 } 320 321 requestParams.remove(UifConstants.UrlParams.LOGIN_USER); 322 setInitialRequestParameters(requestParams); 323 } 324 325 // populate read only fields list 326 if (request.getParameter(UifParameters.READ_ONLY_FIELDS) != null) { 327 String readOnlyFields = request.getParameter(UifParameters.READ_ONLY_FIELDS); 328 setReadOnlyFieldsList(KRADUtils.convertStringParameterToList(readOnlyFields)); 329 } 330 331 // collect dialog response, or initialize new map of responses 332 if (request.getParameter(UifParameters.RETURN_FROM_DIALOG) != null) { 333 String dialogExplanation = null; 334 if ((dialogExplanations != null) && dialogExplanations.containsKey(returnDialogId)) { 335 dialogExplanation = dialogExplanations.get(returnDialogId); 336 } 337 338 DialogResponse response = new DialogResponse(returnDialogId, returnDialogResponse, dialogExplanation); 339 this.dialogResponses.put(this.returnDialogId, response); 340 } else { 341 this.dialogResponses = new HashMap<String, DialogResponse>(); 342 } 343 344 Object historyManager = request.getSession().getAttribute(UifConstants.HistoryFlow.HISTORY_MANAGER); 345 if (historyManager != null && historyManager instanceof HistoryManager) { 346 setHistoryManager((HistoryManager) historyManager); 347 348 String flowKey = request.getParameter(UifConstants.HistoryFlow.FLOW); 349 setFlowKey(flowKey); 350 } 351 352 // clean parameters from XSS attacks that will be written out as hiddens 353 this.pageId = KRADUtils.stripXSSPatterns(this.pageId); 354 this.methodToCall = KRADUtils.stripXSSPatterns(this.methodToCall); 355 this.formKey = KRADUtils.stripXSSPatterns(this.formKey); 356 this.requestedFormKey = KRADUtils.stripXSSPatterns(this.requestedFormKey); 357 this.flowKey = KRADUtils.stripXSSPatterns(this.flowKey); 358 this.sessionId = KRADUtils.stripXSSPatterns(this.sessionId); 359 this.formPostUrl = KRADUtils.stripXSSPatterns(this.formPostUrl); 360 this.returnLocation = KRADUtils.stripXSSPatterns(this.returnLocation); 361 this.returnFormKey = KRADUtils.stripXSSPatterns(this.returnFormKey); 362 this.requestUrl = KRADUtils.stripXSSPatterns(this.requestUrl); 363 } 364 365 /** 366 * {@inheritDoc} 367 */ 368 @Override 369 public void preRender(HttpServletRequest request) { 370 // clear dialog properties so previous values do not appear for new dialogs 371 this.returnDialogId = null; 372 this.returnDialogResponse = null; 373 this.dialogExplanations = new HashMap<String, String>(); 374 } 375 376 /** 377 * Creates the unique id used to store this "conversation" in the session. 378 * The default method generates a java UUID. 379 * 380 * @return UUID 381 */ 382 protected String generateFormKey() { 383 return UUID.randomUUID().toString(); 384 } 385 386 /** 387 * @see org.kuali.rice.krad.uif.view.ViewModel#getViewId() 388 */ 389 @Override 390 public String getViewId() { 391 return this.viewId; 392 } 393 394 /** 395 * @see org.kuali.rice.krad.uif.view.ViewModel#setViewId(String) 396 */ 397 @Override 398 public void setViewId(String viewId) { 399 this.viewId = viewId; 400 } 401 402 /** 403 * @see org.kuali.rice.krad.uif.view.ViewModel#getViewName() 404 */ 405 @Override 406 public String getViewName() { 407 return this.viewName; 408 } 409 410 /** 411 * @see org.kuali.rice.krad.uif.view.ViewModel#setViewName(String) 412 */ 413 @Override 414 public void setViewName(String viewName) { 415 this.viewName = viewName; 416 } 417 418 /** 419 * @see org.kuali.rice.krad.uif.view.ViewModel#getViewTypeName() 420 */ 421 @Override 422 public ViewType getViewTypeName() { 423 return this.viewTypeName; 424 } 425 426 /** 427 * @see org.kuali.rice.krad.uif.view.ViewModel#setViewTypeName(org.kuali.rice.krad.uif.UifConstants.ViewType) 428 */ 429 @Override 430 public void setViewTypeName(ViewType viewTypeName) { 431 this.viewTypeName = viewTypeName; 432 } 433 434 /** 435 * @see org.kuali.rice.krad.uif.view.ViewModel#getPageId() 436 */ 437 @Override 438 public String getPageId() { 439 return this.pageId; 440 } 441 442 /** 443 * @see org.kuali.rice.krad.uif.view.ViewModel#setPageId(String) 444 */ 445 @Override 446 public void setPageId(String pageId) { 447 this.pageId = pageId; 448 } 449 450 /** 451 * @see org.kuali.rice.krad.uif.view.ViewModel#getFormPostUrl() 452 */ 453 @Override 454 public String getFormPostUrl() { 455 return this.formPostUrl; 456 } 457 458 /** 459 * @see org.kuali.rice.krad.uif.view.ViewModel#setFormPostUrl(String) 460 */ 461 @Override 462 public void setFormPostUrl(String formPostUrl) { 463 this.formPostUrl = formPostUrl; 464 } 465 466 /** 467 * Name of the controllerMapping for this form (includes slash) 468 * 469 * @return the controllerMapping string 470 */ 471 public String getControllerMapping() { 472 return controllerMapping; 473 } 474 475 /** 476 * The current {@link HistoryFlow} for this form which stores a trail of urls/breadcrumbs primarily used for 477 * path-based breadcrumb display 478 * 479 * @return the {@link HistoryFlow} 480 */ 481 public HistoryFlow getHistoryFlow() { 482 return historyFlow; 483 } 484 485 /** 486 * Set the current HistoryFlow for this form 487 */ 488 public void setHistoryFlow(HistoryFlow historyFlow) { 489 this.historyFlow = historyFlow; 490 } 491 492 /** 493 * The current {@link HistoryManager} that was pulled from session which store all {@link HistoryFlow} objects in 494 * the current session to keep track of the path the user has taken across views (primarily used by path-based 495 * breadcrumbs) 496 * 497 * @return the HistoryManager 498 */ 499 public HistoryManager getHistoryManager() { 500 return historyManager; 501 } 502 503 /** 504 * Set the current HistoryManager 505 */ 506 public void setHistoryManager(HistoryManager historyManager) { 507 this.historyManager = historyManager; 508 } 509 510 /** 511 * The flowKey representing the HistoryFlow this form may be in. 512 * 513 * <p>This allows for a flow to continue by key or start (if set to "start"). 514 * If null or blank, no flow (or path based 515 * breadcrumbs) are being tracked.</p> 516 * 517 * @return the flowKey 518 */ 519 public String getFlowKey() { 520 return flowKey; 521 } 522 523 /** 524 * Set the flowKey 525 */ 526 public void setFlowKey(String flowKey) { 527 this.flowKey = flowKey; 528 } 529 530 /** 531 * The original requestUrl for the View represented by this form (url received by the controller for initial 532 * request) 533 * 534 * @return the requestUrl 535 */ 536 public String getRequestUrl() { 537 return requestUrl; 538 } 539 540 /** 541 * Set the requestUrl 542 */ 543 public void setRequestUrl(String requestUrl) { 544 this.requestUrl = requestUrl; 545 } 546 547 /** 548 * The requestParameters represent all the parameters in the query string that were initially passed to this View 549 * by the initial request 550 * 551 * @return the requestParameters 552 */ 553 public Map<String, String[]> getInitialRequestParameters() { 554 return initialRequestParameters; 555 } 556 557 /** 558 * Set the requestParameters 559 */ 560 public void setInitialRequestParameters(Map<String, String[]> requestParameters) { 561 this.initialRequestParameters = requestParameters; 562 } 563 564 public String getReturnLocation() { 565 return this.returnLocation; 566 } 567 568 public void setReturnLocation(String returnLocation) { 569 this.returnLocation = returnLocation; 570 } 571 572 public String getReturnFormKey() { 573 return this.returnFormKey; 574 } 575 576 public void setReturnFormKey(String returnFormKey) { 577 this.returnFormKey = returnFormKey; 578 } 579 580 /** 581 * Holds the id for the user's current session 582 * 583 * <p> 584 * The user's session id is used to track when a timeout has occurred and enforce the policy 585 * configured with the {@link org.kuali.rice.krad.uif.view.ViewSessionPolicy}. This property gets initialized 586 * in the {@link #postBind(javax.servlet.http.HttpServletRequest)} method and then is written out as a 587 * hidden on the view. Therefore each post done on the view will send back the session id when the view was 588 * rendering, and the {@link org.kuali.rice.krad.web.filter.UifSessionTimeoutFilter} can use that to determine 589 * if a timeout has occurred 590 * </p> 591 * 592 * @return id for the user's current session 593 */ 594 public String getSessionId() { 595 return sessionId; 596 } 597 598 /** 599 * Holds the configured session timeout interval 600 * 601 * <p> 602 * Holds the session timeout interval so it can be referenced to give the user notifications (for example the 603 * session timeout warning reads this property). This is initialized from the session object in 604 * {@link #postBind(javax.servlet.http.HttpServletRequest)} 605 * </p> 606 * 607 * @return amount of time in milliseconds before the session will timeout 608 */ 609 public int getSessionTimeoutInterval() { 610 return sessionTimeoutInterval; 611 } 612 613 /** 614 * Identifies the controller method that should be invoked to fulfill a 615 * request. The value will be matched up against the 'params' setting on the 616 * {@code RequestMapping} annotation for the controller method 617 * 618 * @return String method to call 619 */ 620 public String getMethodToCall() { 621 return this.methodToCall; 622 } 623 624 /** 625 * Setter for the method to call 626 */ 627 public void setMethodToCall(String methodToCall) { 628 this.methodToCall = methodToCall; 629 } 630 631 /** 632 * {@inheritDoc} 633 */ 634 @Override 635 public Map<String, String> getViewRequestParameters() { 636 return this.viewRequestParameters; 637 } 638 639 /** 640 * {@inheritDoc} 641 */ 642 @Override 643 public void setViewRequestParameters(Map<String, String> viewRequestParameters) { 644 this.viewRequestParameters = viewRequestParameters; 645 } 646 647 /** 648 * {@inheritDoc} 649 */ 650 @Override 651 public List<String> getReadOnlyFieldsList() { 652 return readOnlyFieldsList; 653 } 654 655 /** 656 * {@inheritDoc} 657 */ 658 @Override 659 public void setReadOnlyFieldsList(List<String> readOnlyFieldsList) { 660 this.readOnlyFieldsList = readOnlyFieldsList; 661 } 662 663 /** 664 * @see org.kuali.rice.krad.uif.view.ViewModel#getNewCollectionLines() 665 */ 666 @Override 667 public Map<String, Object> getNewCollectionLines() { 668 return this.newCollectionLines; 669 } 670 671 /** 672 * {@inheritDoc} 673 */ 674 @Override 675 public void setNewCollectionLines(Map<String, Object> newCollectionLines) { 676 this.newCollectionLines = newCollectionLines; 677 } 678 679 /** 680 * {@inheritDoc} 681 */ 682 @Override 683 public String getTriggerActionId() { 684 return triggerActionId; 685 } 686 687 /** 688 * {@inheritDoc} 689 */ 690 @Override 691 public void setTriggerActionId(String triggerActionId) { 692 this.triggerActionId = triggerActionId; 693 } 694 695 /** 696 * @see org.kuali.rice.krad.uif.view.ViewModel#getActionParameters() 697 */ 698 @Override 699 public Map<String, String> getActionParameters() { 700 return this.actionParameters; 701 } 702 703 /** 704 * Returns the action parameters map as a {@code Properties} instance 705 * 706 * @return Properties action parameters 707 */ 708 public Properties getActionParametersAsProperties() { 709 return KRADUtils.convertMapToProperties(actionParameters); 710 } 711 712 /** 713 * {@inheritDoc} 714 */ 715 @Override 716 public void setActionParameters(Map<String, String> actionParameters) { 717 this.actionParameters = actionParameters; 718 } 719 720 /** 721 * Retrieves the value for the given action parameter, or empty string if 722 * not found 723 * 724 * @param actionParameterName - name of the action parameter to retrieve value for 725 * @return String parameter value or empty string 726 */ 727 public String getActionParamaterValue(String actionParameterName) { 728 if ((actionParameters != null) && actionParameters.containsKey(actionParameterName)) { 729 return actionParameters.get(actionParameterName); 730 } 731 732 return ""; 733 } 734 735 /** 736 * Returns the action event that was sent in the action parameters (if any) 737 * 738 * <p> 739 * The action event is a special action parameter that can be sent to indicate a type of action being taken. This 740 * can be looked at by the view or components to render differently 741 * </p> 742 * 743 * TODO: make sure action parameters are getting reinitialized on each request 744 * 745 * @return String action event name or blank if action event was not sent 746 */ 747 public String getActionEvent() { 748 if ((actionParameters != null) && actionParameters.containsKey(UifConstants.UrlParams.ACTION_EVENT)) { 749 return actionParameters.get(UifConstants.UrlParams.ACTION_EVENT); 750 } 751 752 return ""; 753 } 754 755 /** 756 * @see org.kuali.rice.krad.uif.view.ViewModel#getClientStateForSyncing() 757 */ 758 @Override 759 public Map<String, Object> getClientStateForSyncing() { 760 return clientStateForSyncing; 761 } 762 763 /** 764 * Setter for the client state 765 */ 766 public void setClientStateForSyncing(Map<String, Object> clientStateForSyncing) { 767 this.clientStateForSyncing = clientStateForSyncing; 768 } 769 770 /** 771 * @see org.kuali.rice.krad.uif.view.ViewModel#getSelectedCollectionLines() 772 */ 773 @Override 774 public Map<String, Set<String>> getSelectedCollectionLines() { 775 return selectedCollectionLines; 776 } 777 778 /** 779 * {@inheritDoc} 780 */ 781 @Override 782 public void setSelectedCollectionLines(Map<String, Set<String>> selectedCollectionLines) { 783 this.selectedCollectionLines = selectedCollectionLines; 784 } 785 786 /** 787 * Holds Set of String identifiers for lines that were selected in a lookup collection results 788 * across multiple pages. 789 * The value in the cache is preserved in the session across multiple requests. This allows for the 790 * server side paging of results to retain the user choices as they move through the pages. 791 * 792 * @return set of identifiers 793 */ 794 public Set<String> getSelectedLookupResultsCache() { 795 return selectedLookupResultsCache; 796 } 797 798 /** 799 * Sets the lookup result selection cache values 800 */ 801 public void setSelectedLookupResultsCache(Set<String> selectedLookupResultsCache) { 802 this.selectedLookupResultsCache = selectedLookupResultsCache; 803 } 804 805 /** 806 * Key string that identifies the form instance in session storage 807 * 808 * <p> 809 * When the view is posted, the previous form instance is retrieved and then 810 * populated from the request parameters. This key string is retrieve the 811 * session form from the session service 812 * </p> 813 * 814 * @return String form session key 815 */ 816 public String getFormKey() { 817 return this.formKey; 818 } 819 820 /** 821 * Setter for the form's session key 822 */ 823 public void setFormKey(String formKey) { 824 this.formKey = formKey; 825 } 826 827 /** 828 * This is the formKey sent on the original request. It may differ from the actual form key stored in formKey 829 * based on if the form still exists in session by this key or not. 830 * 831 * @return the original requested form key 832 */ 833 public String getRequestedFormKey() { 834 return requestedFormKey; 835 } 836 837 /** 838 * Set the requestedFormKey 839 */ 840 public void setRequestedFormKey(String requestedFormKey) { 841 this.requestedFormKey = requestedFormKey; 842 } 843 844 /** 845 * Indicates whether a redirect has been requested for the view 846 * 847 * @return boolean true if redirect was requested, false if not 848 */ 849 public boolean isRequestRedirected() { 850 return requestRedirected; 851 } 852 853 /** 854 * Setter for the request redirect indicator 855 */ 856 public void setRequestRedirected(boolean requestRedirected) { 857 this.requestRedirected = requestRedirected; 858 } 859 860 /** 861 * Holder for files that are attached through the view 862 * 863 * @return MultipartFile representing the attachment 864 */ 865 public MultipartFile getAttachmentFile() { 866 return this.attachmentFile; 867 } 868 869 /** 870 * Setter for the form's attachment file 871 */ 872 public void setAttachmentFile(MultipartFile attachmentFile) { 873 this.attachmentFile = attachmentFile; 874 } 875 876 /** 877 * @see org.kuali.rice.krad.uif.view.ViewModel#getUpdateComponentId() 878 */ 879 @Override 880 public String getUpdateComponentId() { 881 return updateComponentId; 882 } 883 884 /** 885 * @see org.kuali.rice.krad.uif.view.ViewModel#setUpdateComponentId(java.lang.String) 886 */ 887 @Override 888 public void setUpdateComponentId(String updateComponentId) { 889 this.updateComponentId = updateComponentId; 890 } 891 892 /** 893 * @see org.kuali.rice.krad.uif.view.ViewModel#getUpdateComponent() 894 */ 895 public Component getUpdateComponent() { 896 return updateComponent; 897 } 898 899 /** 900 * @see org.kuali.rice.krad.uif.view.ViewModel#setUpdateComponent(org.kuali.rice.krad.uif.component.Component) 901 */ 902 public void setUpdateComponent(Component updateComponent) { 903 this.updateComponent = updateComponent; 904 } 905 906 /** 907 * @see org.kuali.rice.krad.uif.view.ViewModel#getView() 908 */ 909 @Override 910 public View getView() { 911 return this.view; 912 } 913 914 /** 915 * @see org.kuali.rice.krad.uif.view.ViewModel#setView(org.kuali.rice.krad.uif.view.View) 916 */ 917 @Override 918 public void setView(View view) { 919 this.view = view; 920 } 921 922 /** 923 * Returns an instance of the view's configured view helper service. 924 * 925 * <p>First checks if there is an initialized view containing a view helper instance. If not, and there is 926 * a view id on the form, a call is made to retrieve the view helper instance or class configuration.</p> 927 * 928 * {@inheritDoc} 929 */ 930 @Override 931 public ViewHelperService getViewHelperService() { 932 if ((getView() != null) && (getView().getViewHelperService() != null)) { 933 return getView().getViewHelperService(); 934 } 935 936 String viewId = getViewId(); 937 if (StringUtils.isBlank(viewId) && (getView() != null)) { 938 viewId = getView().getId(); 939 } 940 941 if (StringUtils.isBlank(viewId)) { 942 return null; 943 } 944 945 ViewHelperService viewHelperService = 946 (ViewHelperService) KRADServiceLocatorWeb.getDataDictionaryService().getDictionaryBeanProperty(viewId, 947 UifPropertyPaths.VIEW_HELPER_SERVICE); 948 if (viewHelperService == null) { 949 Class<?> viewHelperServiceClass = 950 (Class<?>) KRADServiceLocatorWeb.getDataDictionaryService().getDictionaryBeanProperty(viewId, 951 UifPropertyPaths.VIEW_HELPER_SERVICE_CLASS); 952 953 if (viewHelperServiceClass != null) { 954 try { 955 viewHelperService = (ViewHelperService) viewHelperServiceClass.newInstance(); 956 } catch (Exception e) { 957 throw new RuntimeException("Unable to instantiate view helper class: " + viewHelperServiceClass, e); 958 } 959 } 960 } 961 962 return viewHelperService; 963 } 964 965 /** 966 * {@inheritDoc} 967 */ 968 @Override 969 public ViewPostMetadata getViewPostMetadata() { 970 return viewPostMetadata; 971 } 972 973 /** 974 * @see UifFormBase#getViewPostMetadata() 975 */ 976 @Override 977 public void setViewPostMetadata(ViewPostMetadata viewPostMetadata) { 978 this.viewPostMetadata = viewPostMetadata; 979 } 980 981 /** 982 * Instance of the {@code ViewService} that can be used to retrieve 983 * {@code View} instances 984 * 985 * @return ViewService implementation 986 */ 987 protected ViewService getViewService() { 988 return KRADServiceLocatorWeb.getViewService(); 989 } 990 991 /** 992 * The jumpToId for this form, the element with this id will be jumped to automatically 993 * when the form is loaded in the view. 994 * Using "TOP" or "BOTTOM" will jump to the top or the bottom of the resulting page. 995 * jumpToId always takes precedence over jumpToName, if set. 996 * 997 * @return the jumpToId 998 */ 999 public String getJumpToId() { 1000 return this.jumpToId; 1001 } 1002 1003 /** 1004 * @param jumpToId the jumpToId to set 1005 */ 1006 public void setJumpToId(String jumpToId) { 1007 this.jumpToId = jumpToId; 1008 } 1009 1010 /** 1011 * The jumpToName for this form, the element with this name will be jumped to automatically 1012 * when the form is loaded in the view. 1013 * WARNING: jumpToId always takes precedence over jumpToName, if set. 1014 * 1015 * @return the jumpToName 1016 */ 1017 public String getJumpToName() { 1018 return this.jumpToName; 1019 } 1020 1021 /** 1022 * @param jumpToName the jumpToName to set 1023 */ 1024 public void setJumpToName(String jumpToName) { 1025 this.jumpToName = jumpToName; 1026 } 1027 1028 /** 1029 * Field to place focus on when the page loads 1030 * An empty focusId will result in focusing on the first visible input element by default. 1031 * 1032 * @return the focusId 1033 */ 1034 public String getFocusId() { 1035 return this.focusId; 1036 } 1037 1038 /** 1039 * @param focusId the focusId to set 1040 */ 1041 public void setFocusId(String focusId) { 1042 this.focusId = focusId; 1043 } 1044 1045 /** 1046 * True when the form is considered dirty (data has changed from original value), false otherwise 1047 * 1048 * <p>For most scenarios, this flag should NOT be set to true. 1049 * If this is set, it must be managed explicitly by the application. This flag exists for marking a 1050 * form dirty from a server call, so it must be changed to false when the form is no longer considered dirty. 1051 * The krad save Action and navigate methodToCall resets this flag back to false, but any other setting of 1052 * this flag must be managed by custom configuration/methods, if custom dirtyForm management is needed.</p> 1053 * 1054 * @return true if the form is considered dirty, false otherwise 1055 */ 1056 public boolean isDirtyForm() { 1057 return dirtyForm; 1058 } 1059 1060 /** 1061 * Sets the dirtyForm flag 1062 * 1063 * <p>For most scenarios, this flag should NOT be set to true. 1064 * If this is set, it must be managed explicitly by the application. This flag exists for marking a 1065 * form dirty from a server call, so it must be changed to false when the form is no longer considered dirty. 1066 * The krad save Action and navigate methodToCall resets this flag back to false, but any other setting of 1067 * this flag must be managed by custom configuration/methods, if custom dirtyForm management is needed.</p> 1068 */ 1069 public void setDirtyForm(boolean dirtyForm) { 1070 this.dirtyForm = dirtyForm; 1071 } 1072 1073 /** 1074 * Set the dirtyForm flag using a String that will be converted to boolean 1075 */ 1076 public void setDirtyForm(String dirtyForm) { 1077 if (dirtyForm != null) { 1078 this.dirtyForm = Boolean.parseBoolean(dirtyForm); 1079 } 1080 } 1081 1082 /** 1083 * Indicates whether the view is rendered within a lightbox 1084 * 1085 * <p> 1086 * Some discussion (for example how a close button behaves) need to change based on whether the 1087 * view is rendered within a lightbox or the standard browser window. This boolean is true when it is 1088 * within a lightbox 1089 * </p> 1090 * 1091 * @return boolean true if view is rendered within a lightbox, false if not 1092 */ 1093 public boolean isRenderedInDialog() { 1094 return this.renderedInDialog; 1095 } 1096 1097 /** 1098 * Setter for the rendered within lightbox indicator 1099 */ 1100 public void setRenderedInDialog(boolean renderedInDialog) { 1101 this.renderedInDialog = renderedInDialog; 1102 } 1103 1104 /** 1105 * Indicates whether the view is rendered within an iframe (this setting must be passed to the View on the url) 1106 * 1107 * @return boolean true if view is rendered within a iframe, false if not 1108 */ 1109 public boolean isRenderedInIframe() { 1110 return renderedInIframe; 1111 } 1112 1113 /** 1114 * @see org.kuali.rice.krad.web.form.UifFormBase#isRenderedInIframe() 1115 */ 1116 public void setRenderedInIframe(boolean renderedInIframe) { 1117 this.renderedInIframe = renderedInIframe; 1118 } 1119 1120 /** 1121 * @see org.kuali.rice.krad.uif.view.ViewModel#isApplyDefaultValues() 1122 */ 1123 @Override 1124 public boolean isApplyDefaultValues() { 1125 return applyDefaultValues; 1126 } 1127 1128 /** 1129 * @see org.kuali.rice.krad.uif.view.ViewModel#setApplyDefaultValues(boolean) 1130 */ 1131 @Override 1132 public void setApplyDefaultValues(boolean applyDefaultValues) { 1133 this.applyDefaultValues = applyDefaultValues; 1134 } 1135 1136 /** 1137 * @see org.kuali.rice.krad.uif.view.ViewModel#isEvaluateFlagsAndModes() 1138 */ 1139 public boolean isEvaluateFlagsAndModes() { 1140 return evaluateFlagsAndModes; 1141 } 1142 1143 /** 1144 * @see org.kuali.rice.krad.uif.view.ViewModel#setEvaluateFlagsAndModes(boolean) 1145 */ 1146 public void setEvaluateFlagsAndModes(boolean evaluateFlagsAndModes) { 1147 this.evaluateFlagsAndModes = evaluateFlagsAndModes; 1148 } 1149 1150 /** 1151 * @see org.kuali.rice.krad.uif.view.ViewModel#isCanEditView() 1152 */ 1153 public Boolean isCanEditView() { 1154 return canEditView; 1155 } 1156 1157 /** 1158 * @see org.kuali.rice.krad.uif.view.ViewModel#setCanEditView(Boolean) 1159 */ 1160 public void setCanEditView(Boolean canEditView) { 1161 this.canEditView = canEditView; 1162 } 1163 1164 /** 1165 * @see org.kuali.rice.krad.uif.view.ViewModel#getActionFlags() 1166 */ 1167 public Map<String, Boolean> getActionFlags() { 1168 return actionFlags; 1169 } 1170 1171 /** 1172 * @see org.kuali.rice.krad.uif.view.ViewModel#setActionFlags(java.util.Map<java.lang.String,java.lang.Boolean>) 1173 */ 1174 public void setActionFlags(Map<String, Boolean> actionFlags) { 1175 this.actionFlags = actionFlags; 1176 } 1177 1178 /** 1179 * @see org.kuali.rice.krad.uif.view.ViewModel#getEditModes() 1180 */ 1181 public Map<String, Boolean> getEditModes() { 1182 return editModes; 1183 } 1184 1185 /** 1186 * @see org.kuali.rice.krad.uif.view.ViewModel#setEditModes(java.util.Map<java.lang.String,java.lang.Boolean>) 1187 */ 1188 public void setEditModes(Map<String, Boolean> editModes) { 1189 this.editModes = editModes; 1190 } 1191 1192 /** 1193 * @see org.kuali.rice.krad.uif.view.ViewModel#getGrowlScript() 1194 */ 1195 @Override 1196 public String getGrowlScript() { 1197 return growlScript; 1198 } 1199 1200 /** 1201 * @see org.kuali.rice.krad.uif.view.ViewModel#setGrowlScript(String) 1202 */ 1203 @Override 1204 public void setGrowlScript(String growlScript) { 1205 this.growlScript = growlScript; 1206 } 1207 1208 /** 1209 * @see org.kuali.rice.krad.uif.view.ViewModel#getState() 1210 */ 1211 @Override 1212 public String getState() { 1213 return state; 1214 } 1215 1216 /** 1217 * @see org.kuali.rice.krad.uif.view.ViewModel#setState(String) 1218 */ 1219 @Override 1220 public void setState(String state) { 1221 this.state = state; 1222 } 1223 1224 /** 1225 * @see org.kuali.rice.krad.uif.view.ViewModel#isAjaxRequest() 1226 */ 1227 @Override 1228 public boolean isAjaxRequest() { 1229 return ajaxRequest; 1230 } 1231 1232 /** 1233 * @see org.kuali.rice.krad.uif.view.ViewModel#setAjaxRequest(boolean) 1234 */ 1235 @Override 1236 public void setAjaxRequest(boolean ajaxRequest) { 1237 this.ajaxRequest = ajaxRequest; 1238 } 1239 1240 /** 1241 * @see org.kuali.rice.krad.uif.view.ViewModel#getAjaxReturnType() 1242 */ 1243 @Override 1244 public String getAjaxReturnType() { 1245 return ajaxReturnType; 1246 } 1247 1248 /** 1249 * @see org.kuali.rice.krad.uif.view.ViewModel#setAjaxReturnType(String) 1250 */ 1251 @Override 1252 public void setAjaxReturnType(String ajaxReturnType) { 1253 this.ajaxReturnType = ajaxReturnType; 1254 } 1255 1256 /** 1257 * @see org.kuali.rice.krad.uif.view.ViewModel#isUpdateComponentRequest() 1258 */ 1259 @Override 1260 public boolean isUpdateComponentRequest() { 1261 return isAjaxRequest() && StringUtils.isNotBlank(getAjaxReturnType()) && getAjaxReturnType().equals( 1262 UifConstants.AjaxReturnTypes.UPDATECOMPONENT.getKey()); 1263 } 1264 1265 /** 1266 * @see org.kuali.rice.krad.uif.view.ViewModel#isUpdateDialogRequest() 1267 */ 1268 @Override 1269 public boolean isUpdateDialogRequest() { 1270 return isAjaxRequest() && StringUtils.isNotBlank(getAjaxReturnType()) && getAjaxReturnType().equals( 1271 UifConstants.AjaxReturnTypes.UPDATEDIALOG.getKey()); 1272 } 1273 1274 /** 1275 * @see org.kuali.rice.krad.uif.view.ViewModel#isUpdatePageRequest() 1276 */ 1277 @Override 1278 public boolean isUpdatePageRequest() { 1279 return StringUtils.isNotBlank(getAjaxReturnType()) && getAjaxReturnType().equals( 1280 UifConstants.AjaxReturnTypes.UPDATEPAGE.getKey()); 1281 } 1282 1283 /** 1284 * @see org.kuali.rice.krad.uif.view.ViewModel#isUpdateNoneRequest() 1285 */ 1286 @Override 1287 public boolean isUpdateNoneRequest() { 1288 return StringUtils.isNotBlank(getAjaxReturnType()) && getAjaxReturnType().equals( 1289 UifConstants.AjaxReturnTypes.UPDATENONE.getKey()); 1290 } 1291 1292 /** 1293 * @see org.kuali.rice.krad.uif.view.ViewModel#isJsonRequest() 1294 */ 1295 @Override 1296 public boolean isJsonRequest() { 1297 return StringUtils.isNotBlank(getRequestJsonTemplate()); 1298 } 1299 1300 /** 1301 * @see org.kuali.rice.krad.uif.view.ViewModel#getRequestJsonTemplate() 1302 */ 1303 @Override 1304 public String getRequestJsonTemplate() { 1305 return requestJsonTemplate; 1306 } 1307 1308 /** 1309 * @see org.kuali.rice.krad.uif.view.ViewModel#setRequestJsonTemplate 1310 */ 1311 @Override 1312 public void setRequestJsonTemplate(String requestJsonTemplate) { 1313 this.requestJsonTemplate = requestJsonTemplate; 1314 } 1315 1316 /** 1317 * {@inheritDoc} 1318 */ 1319 @Override 1320 public boolean isCollectionPagingRequest() { 1321 return collectionPagingRequest; 1322 } 1323 1324 /** 1325 * {@inheritDoc} 1326 */ 1327 @Override 1328 public void setCollectionPagingRequest(boolean collectionPagingRequest) { 1329 this.collectionPagingRequest = collectionPagingRequest; 1330 } 1331 1332 /** 1333 * For cases where the request was triggered from within a dialog, we want to show that dialog, 1334 * identified by this id, again. 1335 */ 1336 public String getShowDialogId() { 1337 return showDialogId; 1338 } 1339 1340 /** 1341 * @see UifFormBase#getShowDialogId() 1342 */ 1343 public void setShowDialogId(String dialogId) { 1344 this.showDialogId = dialogId; 1345 } 1346 1347 /** 1348 * Used by the dialog framework to set the dialog id for a return dialog call (when the server has 1349 * triggered a dialog). 1350 * 1351 * <p>Note this is a request only property. On a return call the value for this gets pulled and used to 1352 * create an entry in {@link UifFormBase#getDialogResponses()}</p> 1353 * 1354 * @return String id for the dialog being returned from 1355 */ 1356 public String getReturnDialogId() { 1357 return returnDialogId; 1358 } 1359 1360 /** 1361 * @see UifFormBase#getReturnDialogId() 1362 */ 1363 public void setReturnDialogId(String returnDialogId) { 1364 this.returnDialogId = returnDialogId; 1365 } 1366 1367 /** 1368 * Used by the dialog framework to set the dialog response for a return dialog call (when the server has 1369 * triggered a dialog). 1370 * 1371 * <p>Note this is a request only property. On a return call the value for this gets pulled and used to 1372 * create an entry in {@link UifFormBase#getDialogResponses()}</p> 1373 * 1374 * @return String response for the dialog being returned from 1375 */ 1376 public String getReturnDialogResponse() { 1377 return returnDialogResponse; 1378 } 1379 1380 /** 1381 * @see UifFormBase#getReturnDialogResponse() 1382 */ 1383 public void setReturnDialogResponse(String returnDialogResponse) { 1384 this.returnDialogResponse = returnDialogResponse; 1385 } 1386 1387 /** 1388 * {@inheritDoc} 1389 */ 1390 @Override 1391 public Map<String, String> getDialogExplanations() { 1392 return dialogExplanations; 1393 } 1394 1395 /** 1396 * {@inheritDoc} 1397 */ 1398 @Override 1399 public void setDialogExplanations(Map<String, String> dialogExplanations) { 1400 this.dialogExplanations = dialogExplanations; 1401 } 1402 1403 /** 1404 * {@inheritDoc} 1405 */ 1406 @Override 1407 public Map<String, DialogResponse> getDialogResponses() { 1408 return dialogResponses; 1409 } 1410 1411 /** 1412 * {@inheritDoc} 1413 */ 1414 @Override 1415 public DialogResponse getDialogResponse(String dialogId) { 1416 if ((dialogResponses != null) && dialogResponses.containsKey(dialogId)) { 1417 return dialogResponses.get(dialogId); 1418 } 1419 1420 return null; 1421 } 1422 1423 /** 1424 * {@inheritDoc} 1425 */ 1426 @Override 1427 public void setDialogResponses(Map<String, DialogResponse> dialogResponses) { 1428 this.dialogResponses = dialogResponses; 1429 } 1430 1431 /** 1432 * @see org.kuali.rice.krad.uif.view.ViewModel#getExtensionData() 1433 */ 1434 @Override 1435 public Map<String, Object> getExtensionData() { 1436 return extensionData; 1437 } 1438 1439 /** 1440 * {@inheritDoc} 1441 */ 1442 @Override 1443 public void setExtensionData(Map<String, Object> extensionData) { 1444 this.extensionData = extensionData; 1445 } 1446 1447 /** 1448 * Http servlet request instance for the current request being processed. 1449 * 1450 * @return HttpServletRequest instance 1451 */ 1452 public HttpServletRequest getRequest() { 1453 return request; 1454 } 1455 1456 /** 1457 * @see UifFormBase#getRequest() 1458 */ 1459 public void setRequest(HttpServletRequest request) { 1460 this.request = request; 1461 } 1462 1463 /** 1464 * The {@code List} that contains all newly added items for the collections on the model 1465 * 1466 * <p> 1467 * This list contains the new items for all the collections on the model. 1468 * </p> 1469 * 1470 * @return List of the newly added item lists 1471 */ 1472 public List getAddedCollectionItems() { 1473 return addedCollectionItems; 1474 } 1475 1476 /** 1477 * Setter for the newly added item list 1478 */ 1479 public void setAddedCollectionItems(List addedCollectionItems) { 1480 this.addedCollectionItems = addedCollectionItems; 1481 } 1482 1483 /** 1484 * Indicates whether an collection item has been newly added 1485 * 1486 * <p> 1487 * Tests collection items against the list of newly added items on the model. This list gets cleared when the view 1488 * is submitted and the items are persisted. 1489 * </p> 1490 * 1491 * @param item - the item to test against list of newly added items 1492 * @return boolean true if the item has been newly added 1493 */ 1494 public boolean isAddedCollectionItem(Object item) { 1495 return addedCollectionItems.contains(item); 1496 } 1497 1498 /** 1499 * The data object to bind to for a dialog 1500 * 1501 * <p>The data object serves as a placeholder for temporary properties that might be used within a dialog. The 1502 * purpose of placeholder is to provide a separation between the dialog object and the underlying object for use 1503 * in cases like object manipulation.</p> 1504 */ 1505 public Object getDialogDataObject() { 1506 return dialogDataObject; 1507 } 1508 1509 /** 1510 * @see UifFormBase#getDialogDataObject() 1511 */ 1512 public void setDialogDataObject(Object dataObject) { 1513 this.dialogDataObject = dataObject; 1514 } 1515 1516 @Override 1517 public String toString() { 1518 StringBuilder builder = new StringBuilder(); 1519 builder.append(getClass().getSimpleName()).append(" [viewId=").append(this.viewId).append(", viewName=").append( 1520 this.viewName).append(", viewTypeName=").append(this.viewTypeName).append(", pageId=").append( 1521 this.pageId).append(", methodToCall=").append(this.methodToCall).append(", formKey=").append( 1522 this.formKey).append(", requestedFormKey=").append(this.requestedFormKey).append("]"); 1523 return builder.toString(); 1524 } 1525}