001/** 002 * Copyright 2005-2016 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.kns.web.struts.form; 017 018import org.apache.commons.lang.StringUtils; 019import org.apache.struts.action.ActionMapping; 020import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator; 021import org.kuali.rice.core.web.format.Formatter; 022import org.kuali.rice.kns.datadictionary.HeaderNavigation; 023import org.kuali.rice.kns.util.ActionFormUtilMap; 024import org.kuali.rice.kns.util.WebUtils; 025import org.kuali.rice.kns.web.struts.form.pojo.PojoFormBase; 026import org.kuali.rice.kns.web.ui.ExtraButton; 027import org.kuali.rice.kns.web.ui.HeaderField; 028import org.kuali.rice.krad.util.KRADConstants; 029import org.kuali.rice.krad.util.ObjectUtils; 030import org.springframework.util.AutoPopulatingList; 031 032import javax.servlet.ServletRequest; 033import javax.servlet.http.HttpServletRequest; 034import java.util.ArrayList; 035import java.util.HashMap; 036import java.util.List; 037import java.util.Map; 038 039/** 040 * This class common properites for all action forms. 041 */ 042public class KualiForm extends PojoFormBase { 043 /** 044 * Tab state UI literals 045 */ 046 public static enum TabState { 047 OPEN, 048 CLOSE 049 } 050 051 private static final long serialVersionUID = 1L; 052 053 private static final String literalPrefixAndDelimiter = 054 KRADConstants.LOOKUP_PARAMETER_LITERAL_PREFIX+ KRADConstants.LOOKUP_PARAMETER_LITERAL_DELIMITER; 055 056 private String backLocation; 057 private String methodToCall; 058 private String refreshCaller; 059 private String anchor; 060 private Map<String, String> tabStates; 061 private Map actionFormUtilMap; 062 private Map displayedErrors = new HashMap(); 063 private Map<String, Object> displayedWarnings = new HashMap<String, Object>(); 064 private Map<String, Object> displayedInfo = new HashMap<String, Object>(); 065 private int currentTabIndex = 0; 066 private int arbitrarilyHighIndex = 1000000; 067 068 private String navigationCss; 069 private HeaderNavigation[] headerNavigationTabs; 070 protected List<ExtraButton> extraButtons = new AutoPopulatingList( ExtraButton.class ) ; 071 072 private boolean fieldLevelHelpEnabled; 073 074 private List<HeaderField> docInfo; 075 private int numColumns = 2; 076 077 private String fieldNameToFocusOnAfterSubmit; 078 079 /** 080 * @see org.kuali.rice.krad.web.struts.pojo.PojoFormBase#addRequiredNonEditableProperties() 081 */ 082 @Override 083 public void addRequiredNonEditableProperties(){ 084 super.addRequiredNonEditableProperties(); 085 registerRequiredNonEditableProperty(KRADConstants.REFRESH_CALLER); 086 } 087 088 public int getNumColumns() { 089 return this.numColumns; 090 } 091 092 public void setNumColumns(int numColumns) { 093 this.numColumns = numColumns; 094 } 095 096 public List<HeaderField> getDocInfo() { 097 return this.docInfo; 098 } 099 100 public void setDocInfo(List<HeaderField> docInfo) { 101 this.docInfo = docInfo; 102 } 103 104 /** 105 * no args constructor which must init our tab states list 106 */ 107 public KualiForm() { 108 this.tabStates = new HashMap<String, String>(); 109 this.actionFormUtilMap = new ActionFormUtilMap(); 110 this.docInfo = new ArrayList<HeaderField>(); 111 } 112 113 /** 114 * Checks for methodToCall parameter, and if not populated in form calls utility method to parse the string from the request. 115 */ 116 public void populate(HttpServletRequest request) { 117 setMethodToCall(WebUtils.parseMethodToCall(this, request)); 118 119 super.populate(request); 120 121 populateBackLocation(request); 122 populateFieldLevelHelpEnabled(request); 123 124 if (actionFormUtilMap instanceof ActionFormUtilMap) { 125 ((ActionFormUtilMap) actionFormUtilMap).setCacheValueFinderResults(true); 126 } 127 } 128 129 private static Boolean ENABLE_FIELD_LEVEL_HELP_IND; 130 131 protected void populateBackLocation(HttpServletRequest request){ 132 if (getParameter(request, "returnLocation") != null) { 133 setBackLocation(getParameter(request, "returnLocation")); 134 } 135 } 136 137 /** 138 * Populates whether the each field will have field-level help associated with it. Depending on how the jsp/tags are implemented, the value 139 * populated by this method may be overruled by other settings 140 * 141 * @param request 142 */ 143 protected void populateFieldLevelHelpEnabled(HttpServletRequest request) { 144 boolean fieldLevelHelpEnabled = CoreFrameworkServiceLocator.getParameterService().getParameterValueAsBoolean( 145 KRADConstants.KNS_NAMESPACE, KRADConstants.DetailTypes.ALL_DETAIL_TYPE, 146 KRADConstants.SystemGroupParameterNames.ENABLE_FIELD_LEVEL_HELP_IND, Boolean.FALSE); 147 setFieldLevelHelpEnabled(fieldLevelHelpEnabled); 148 } 149 150 public Map getDisplayedErrors() { 151 return displayedErrors; 152 } 153 154 /** 155 * @return the displayedWarnings 156 */ 157 public Map<String, Object> getDisplayedWarnings() { 158 return this.displayedWarnings; 159 } 160 161 /** 162 * @return the displayedInfo 163 */ 164 public Map<String, Object> getDisplayedInfo() { 165 return this.displayedInfo; 166 } 167 168 /** 169 * Used by the dispatch action to determine which action method to call into. 170 * 171 * @return Returns the methodToCall. 172 */ 173 public String getMethodToCall() { 174 return methodToCall; 175 } 176 177 178 /** 179 * @param methodToCall The methodToCall to set. 180 */ 181 public void setMethodToCall(String methodToCall) { 182 this.methodToCall = methodToCall; 183 } 184 185 186 /** 187 * Can be used by actions refresh method to determine what called the the refresh method. 188 * 189 * @return Returns the refreshCaller. 190 */ 191 public String getRefreshCaller() { 192 return refreshCaller; 193 } 194 195 196 /** 197 * @param refreshCaller The refreshCaller to set. 198 */ 199 public void setRefreshCaller(String refreshCaller) { 200 this.refreshCaller = refreshCaller; 201 } 202 203 /** 204 * @return the tab state list 205 */ 206 public Map<String, String> getTabStates() { 207 return tabStates; 208 } 209 210 /** 211 * simple setter for the tab state Map 212 * 213 * @param tabStates 214 */ 215 public void setTabStates(Map<String, String> tabStates) { 216 this.tabStates = tabStates; 217 } 218 219 /** 220 * Special getter based on key to work with multi rows for tab state objects 221 */ 222 public String getTabState(String key) { 223 String state = KRADConstants.EMPTY_STRING; 224 if (tabStates.containsKey(key)) { 225 if (tabStates.get(key) instanceof String) { 226 state = tabStates.get(key); 227 } 228 else { 229 //This is the case where the value is an Array of String, 230 //so we'll have to get the first element 231 Object result = tabStates.get(key); 232 result.getClass(); 233 state = ((String[])result)[0]; 234 } 235 } 236 237 return state; 238 } 239 240 public int getCurrentTabIndex() { 241 return currentTabIndex; 242 } 243 244 public void setCurrentTabIndex(int currentTabIndex) { 245 this.currentTabIndex = currentTabIndex; 246 } 247 248 public void incrementTabIndex() { 249 this.currentTabIndex++; 250 } 251 252 public int getNextArbitrarilyHighIndex() { 253 return this.arbitrarilyHighIndex++; 254 } 255 256 public String getFieldNameToFocusOnAfterSubmit() { 257 return this.fieldNameToFocusOnAfterSubmit; 258 } 259 260 public void setFieldNameToFocusOnAfterSubmit(String fieldNameToFocusOnAfterSubmit) { 261 this.fieldNameToFocusOnAfterSubmit = fieldNameToFocusOnAfterSubmit; 262 } 263 264 /** 265 * @return Returns the validOptionsMap. 266 */ 267 public Map getActionFormUtilMap() { 268 return actionFormUtilMap; 269 } 270 271 /** 272 * @param validOptionsMap The validOptionsMap to set. 273 */ 274 public void setActionFormUtilMap(Map validOptionsMap) { 275 this.actionFormUtilMap = validOptionsMap; 276 } 277 278 /** 279 * Gets the headerNavigationTabs attribute. 280 * 281 * @return Returns the headerNavigationTabs. 282 */ 283 public HeaderNavigation[] getHeaderNavigationTabs() { 284 return headerNavigationTabs; 285 } 286 287 /** 288 * Sets the headerNavigationTabs attribute value. 289 * 290 * @param headerNavigationTabs The headerNavigationTabs to set. 291 */ 292 public void setHeaderNavigationTabs(HeaderNavigation[] headerNavigationTabs) { 293 this.headerNavigationTabs = headerNavigationTabs; 294 } 295 296 /** 297 * Gets the navigationCss attribute. 298 * 299 * @return Returns the navigationCss. 300 */ 301 public String getNavigationCss() { 302 return navigationCss; 303 } 304 305 /** 306 * Sets the navigationCss attribute value. 307 * 308 * @param navigationCss The navigationCss to set. 309 */ 310 public void setNavigationCss(String navigationCss) { 311 this.navigationCss = navigationCss; 312 } 313 314 public String getAnchor() { 315 return anchor; 316 } 317 318 public void setAnchor(String anchor) { 319 this.anchor = anchor; 320 } 321 322 public List<ExtraButton> getExtraButtons() { 323 return extraButtons; 324 } 325 326 public void setExtraButtons(List<ExtraButton> extraButtons) { 327 if ( extraButtons instanceof AutoPopulatingList ) { 328 this.extraButtons = extraButtons; 329 } else { 330 this.extraButtons.clear(); 331 this.extraButtons.addAll( extraButtons ); 332 } 333 } 334 335 public ExtraButton getExtraButton( int index ) { 336 return extraButtons.get( index ); 337 } 338 339 public void setExtraButton( int index, ExtraButton extraButton ) { 340 extraButtons.set( index, extraButton ); 341 } 342 343 /** 344 * Returns whether field level help is enabled for this form. 345 * 346 * @return 347 */ 348 public boolean isFieldLevelHelpEnabled() { 349 return this.fieldLevelHelpEnabled; 350 } 351 352 public void setFieldLevelHelpEnabled(boolean fieldLevelHelpEnabled) { 353 this.fieldLevelHelpEnabled = fieldLevelHelpEnabled; 354 } 355 356 357 /** 358 * Retrieves a value from the form for the purposes of passing it as a parameter into the lookup or inquiry frameworks 359 * 360 * @param parameterName the name of the parameter, as expected by the lookup or inquiry frameworks 361 * @param parameterValueLocation the name of the property containing the value of the parameter 362 * @return the value of the parameter 363 */ 364 public String retrieveFormValueForLookupInquiryParameters(String parameterName, String parameterValueLocation) { 365 // dereference literal values by simply trimming of the prefix 366 if (parameterValueLocation.startsWith(literalPrefixAndDelimiter)) { 367 return parameterValueLocation.substring(literalPrefixAndDelimiter.length()); 368 } 369 370 Object value = ObjectUtils.getPropertyValue(this, parameterValueLocation); 371 if (value == null) { 372 return null; 373 } 374 if (value instanceof String) { 375 return (String) value; 376 } 377 Formatter formatter = Formatter.getFormatter(value.getClass()); 378 return (String) formatter.format(value); 379 } 380 381 /** 382 * This overridden method ... 383 * 384 * @see org.kuali.rice.krad.web.struts.pojo.PojoFormBase#shouldPropertyBePopulatedInForm(java.lang.String, javax.servlet.http.HttpServletRequest) 385 */ 386 @Override 387 public boolean shouldPropertyBePopulatedInForm( 388 String requestParameterName, HttpServletRequest request) { 389 if (requestParameterName.startsWith(KRADConstants.TAB_STATES)) { 390 return true; 391 } 392 393 if (requestParameterName.equals(KRADConstants.DISPATCH_REQUEST_PARAMETER)) { 394 String methodToCallParameterName = request.getParameter(KRADConstants.DISPATCH_REQUEST_PARAMETER); 395 if(StringUtils.equals(methodToCallParameterName, KRADConstants.RETURN_METHOD_TO_CALL)){ 396 return true; 397 } 398 } 399 400 return super.shouldPropertyBePopulatedInForm(requestParameterName, request); 401 } 402 403 public boolean shouldMethodToCallParameterBeUsed(String methodToCallParameterName, String methodToCallParameterValue, HttpServletRequest request) { 404 if ("GET".equalsIgnoreCase(request.getMethod())) { 405 return true; 406 } 407 if (shouldPropertyBePopulatedInForm(methodToCallParameterName, request)) { 408 return true; 409 } 410 if (methodToCallParameterName != null && WebUtils.endsWithCoordinates(methodToCallParameterName)) { 411 methodToCallParameterName = methodToCallParameterName.substring(0, WebUtils.getIndexOfCoordinateExtension(methodToCallParameterName)); 412 if (shouldPropertyBePopulatedInForm(methodToCallParameterName, request)) { 413 return true; 414 } 415 } 416 if (KRADConstants.METHOD_TO_CALL_PATH.equals(methodToCallParameterName)) { 417 if (shouldPropertyBePopulatedInForm(methodToCallParameterValue, request)) { 418 return true; 419 } 420 if (methodToCallParameterValue != null && WebUtils.endsWithCoordinates(methodToCallParameterName)) { 421 methodToCallParameterValue = methodToCallParameterValue.substring(0, WebUtils 422 .getIndexOfCoordinateExtension(methodToCallParameterName)); 423 if (shouldPropertyBePopulatedInForm(methodToCallParameterValue, request)) { 424 return true; 425 } 426 } 427 } 428 return false; 429 } 430 431 /** 432 * @see org.kuali.rice.krad.web.struts.pojo.PojoFormBase#clearEditablePropertyInformation() 433 */ 434 @Override 435 public void clearEditablePropertyInformation() { 436 super.clearEditablePropertyInformation(); 437 } 438 439 public void setDerivedValuesOnForm(HttpServletRequest request) { 440 } 441 442 /** 443 * @see org.apache.struts.action.ActionForm#reset(org.apache.struts.action.ActionMapping, javax.servlet.http.HttpServletRequest) 444 */ 445 @Override 446 public void reset(ActionMapping mapping, HttpServletRequest request) { 447 super.reset(mapping, request); 448 if (extraButtons != null) { 449 extraButtons.clear(); 450 } 451 //fieldNameToFocusOnAfterSubmit = ""; 452 clearDisplayedMessages(); 453 } 454 455 /** 456 * @see org.apache.struts.action.ActionForm#reset(org.apache.struts.action.ActionMapping, javax.servlet.ServletRequest) 457 */ 458 @Override 459 public void reset(ActionMapping mapping, ServletRequest request) { 460 super.reset(mapping, request); 461 if (extraButtons != null) { 462 extraButtons.clear(); 463 } 464 //fieldNameToFocusOnAfterSubmit = ""; 465 clearDisplayedMessages(); 466 } 467 468 private void clearDisplayedMessages() { 469 if (displayedErrors != null) { 470 displayedErrors.clear(); 471 } 472 if (displayedWarnings != null) { 473 displayedWarnings.clear(); 474 } 475 if (displayedInfo != null) { 476 displayedInfo.clear(); 477 } 478 } 479 480 /** 481 * @return the backLocation 482 */ 483 public String getBackLocation() { 484 return WebUtils.sanitizeBackLocation(this.backLocation); 485 } 486 487 /** 488 * @param backLocation the backLocation to set 489 */ 490 public void setBackLocation(String backLocation) { 491 this.backLocation = backLocation; 492 } 493 494}