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.kns.web.struts.form;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.apache.struts.action.ActionMapping;
20  import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator;
21  import org.kuali.rice.core.web.format.Formatter;
22  import org.kuali.rice.kns.datadictionary.HeaderNavigation;
23  import org.kuali.rice.kns.util.ActionFormUtilMap;
24  import org.kuali.rice.kns.util.WebUtils;
25  import org.kuali.rice.kns.web.struts.form.pojo.PojoFormBase;
26  import org.kuali.rice.kns.web.ui.ExtraButton;
27  import org.kuali.rice.kns.web.ui.HeaderField;
28  import org.kuali.rice.krad.util.KRADConstants;
29  import org.kuali.rice.krad.util.ObjectUtils;
30  import org.springframework.util.AutoPopulatingList;
31  
32  import javax.servlet.ServletRequest;
33  import javax.servlet.http.HttpServletRequest;
34  import java.util.ArrayList;
35  import java.util.HashMap;
36  import java.util.List;
37  import java.util.Map;
38  
39  /**
40   * This class common properites for all action forms.
41   */
42  public class KualiForm extends PojoFormBase {
43      /**
44       * Tab state UI literals
45       */
46      public static enum TabState {
47          OPEN,
48          CLOSE
49      }
50  
51      private static final long serialVersionUID = 1L;
52  
53      private static final String literalPrefixAndDelimiter =
54      	KRADConstants.LOOKUP_PARAMETER_LITERAL_PREFIX+ KRADConstants.LOOKUP_PARAMETER_LITERAL_DELIMITER;
55  
56      private String backLocation;
57      private String methodToCall;
58      private String refreshCaller;
59      private String anchor;
60      private Map<String, String> tabStates;
61      private Map actionFormUtilMap;
62      private Map displayedErrors = new HashMap();
63      private Map<String, Object> displayedWarnings = new HashMap<String, Object>();
64      private Map<String, Object> displayedInfo = new HashMap<String, Object>();
65      private int currentTabIndex = 0;
66      private int arbitrarilyHighIndex = 1000000;
67  
68      private String navigationCss;
69      private HeaderNavigation[] headerNavigationTabs;
70      protected List<ExtraButton> extraButtons = new AutoPopulatingList( ExtraButton.class ) ;
71  
72      private boolean fieldLevelHelpEnabled;
73      
74      private List<HeaderField> docInfo;
75      private int numColumns = 2;
76      
77      private String fieldNameToFocusOnAfterSubmit;
78      
79      /**
80       * @see org.kuali.rice.krad.web.struts.pojo.PojoFormBase#addRequiredNonEditableProperties()
81       */
82      @Override
83      public void addRequiredNonEditableProperties(){
84      	super.addRequiredNonEditableProperties();
85      	registerRequiredNonEditableProperty(KRADConstants.REFRESH_CALLER);
86      }
87      
88      public int getNumColumns() {
89          return this.numColumns;
90      }
91  
92      public void setNumColumns(int numColumns) {
93          this.numColumns = numColumns;
94      }
95  
96      public List<HeaderField> getDocInfo() {
97          return this.docInfo;
98      }
99  
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     	if ( ENABLE_FIELD_LEVEL_HELP_IND == null ) {
145     		ENABLE_FIELD_LEVEL_HELP_IND = CoreFrameworkServiceLocator.getParameterService().getParameterValueAsBoolean(
146                     KRADConstants.KNS_NAMESPACE,
147                     KRADConstants.DetailTypes.ALL_DETAIL_TYPE, KRADConstants.SystemGroupParameterNames.ENABLE_FIELD_LEVEL_HELP_IND, Boolean.FALSE);
148     	}
149     	setFieldLevelHelpEnabled( ENABLE_FIELD_LEVEL_HELP_IND);
150     }
151 
152     public Map getDisplayedErrors() {
153         return displayedErrors;
154     }
155 
156     /**
157 	 * @return the displayedWarnings
158 	 */
159 	public Map<String, Object> getDisplayedWarnings() {
160 		return this.displayedWarnings;
161 	}
162 
163 	/**
164 	 * @return the displayedInfo
165 	 */
166 	public Map<String, Object> getDisplayedInfo() {
167 		return this.displayedInfo;
168 	}
169 
170 	/**
171      * Used by the dispatch action to determine which action method to call into.
172      *
173      * @return Returns the methodToCall.
174      */
175     public String getMethodToCall() {
176         return methodToCall;
177     }
178 
179 
180     /**
181      * @param methodToCall The methodToCall to set.
182      */
183     public void setMethodToCall(String methodToCall) {
184         this.methodToCall = methodToCall;
185     }
186 
187 
188     /**
189      * Can be used by actions refresh method to determine what called the the refresh method.
190      *
191      * @return Returns the refreshCaller.
192      */
193     public String getRefreshCaller() {
194         return refreshCaller;
195     }
196 
197 
198     /**
199      * @param refreshCaller The refreshCaller to set.
200      */
201     public void setRefreshCaller(String refreshCaller) {
202         this.refreshCaller = refreshCaller;
203     }
204 
205     /**
206      * @return the tab state list
207      */
208     public Map<String, String> getTabStates() {
209         return tabStates;
210     }
211 
212     /**
213      * simple setter for the tab state Map
214      *
215      * @param tabStates
216      */
217     public void setTabStates(Map<String, String> tabStates) {
218         this.tabStates = tabStates;
219     }
220 
221     /**
222      * Special getter based on key to work with multi rows for tab state objects
223      */
224     public String getTabState(String key) {
225         String state = KRADConstants.EMPTY_STRING;
226         if (tabStates.containsKey(key)) {
227             if (tabStates.get(key) instanceof String) {
228             	state = tabStates.get(key);
229             }
230             else {
231             	//This is the case where the value is an Array of String,
232             	//so we'll have to get the first element
233             	Object result = tabStates.get(key);
234             	result.getClass();
235             	state = ((String[])result)[0];
236             }
237         }
238 
239         return state;
240     }
241 
242     public int getCurrentTabIndex() {
243         return currentTabIndex;
244     }
245 
246     public void setCurrentTabIndex(int currentTabIndex) {
247         this.currentTabIndex = currentTabIndex;
248     }
249 
250     public void incrementTabIndex() {
251         this.currentTabIndex++;
252     }
253 
254     public int getNextArbitrarilyHighIndex() {
255         return this.arbitrarilyHighIndex++;
256     }
257     
258 	public String getFieldNameToFocusOnAfterSubmit() {
259 		return this.fieldNameToFocusOnAfterSubmit;
260 	}
261 
262 	public void setFieldNameToFocusOnAfterSubmit(String fieldNameToFocusOnAfterSubmit) {
263 		this.fieldNameToFocusOnAfterSubmit = fieldNameToFocusOnAfterSubmit;
264 	}
265 
266 	/**
267      * @return Returns the validOptionsMap.
268      */
269     public Map getActionFormUtilMap() {
270         return actionFormUtilMap;
271     }
272 
273     /**
274      * @param validOptionsMap The validOptionsMap to set.
275      */
276     public void setActionFormUtilMap(Map validOptionsMap) {
277         this.actionFormUtilMap = validOptionsMap;
278     }
279 
280     /**
281      * Gets the headerNavigationTabs attribute.
282      *
283      * @return Returns the headerNavigationTabs.
284      */
285     public HeaderNavigation[] getHeaderNavigationTabs() {
286         return headerNavigationTabs;
287     }
288 
289     /**
290      * Sets the headerNavigationTabs attribute value.
291      *
292      * @param headerNavigationTabs The headerNavigationTabs to set.
293      */
294     public void setHeaderNavigationTabs(HeaderNavigation[] headerNavigationTabs) {
295         this.headerNavigationTabs = headerNavigationTabs;
296     }
297 
298     /**
299      * Gets the navigationCss attribute.
300      *
301      * @return Returns the navigationCss.
302      */
303     public String getNavigationCss() {
304         return navigationCss;
305     }
306 
307     /**
308      * Sets the navigationCss attribute value.
309      *
310      * @param navigationCss The navigationCss to set.
311      */
312     public void setNavigationCss(String navigationCss) {
313         this.navigationCss = navigationCss;
314     }
315 
316     public String getAnchor() {
317         return anchor;
318     }
319 
320     public void setAnchor(String anchor) {
321         this.anchor = anchor;
322     }
323 
324     public List<ExtraButton> getExtraButtons() {
325         return extraButtons;
326     }
327 
328     public void setExtraButtons(List<ExtraButton> extraButtons) {
329         if ( extraButtons instanceof AutoPopulatingList ) {
330             this.extraButtons = extraButtons;
331         } else {
332             this.extraButtons.clear();
333             this.extraButtons.addAll( extraButtons );
334         }
335     }
336 
337     public ExtraButton getExtraButton( int index ) {
338         return extraButtons.get( index );
339     }
340 
341     public void setExtraButton( int index, ExtraButton extraButton ) {
342         extraButtons.set( index, extraButton );
343     }
344 
345     /**
346      * Returns whether field level help is enabled for this form.
347      * 
348      * @return
349      */
350     public boolean isFieldLevelHelpEnabled() {
351         return this.fieldLevelHelpEnabled;
352     }
353 
354     public void setFieldLevelHelpEnabled(boolean fieldLevelHelpEnabled) {
355         this.fieldLevelHelpEnabled = fieldLevelHelpEnabled;
356     }
357     
358     
359     /**
360      * Retrieves a value from the form for the purposes of passing it as a parameter into the lookup or inquiry frameworks 
361      * 
362      * @param parameterName the name of the parameter, as expected by the lookup or inquiry frameworks
363      * @param parameterValueLocation the name of the property containing the value of the parameter
364      * @return the value of the parameter
365      */
366     public String retrieveFormValueForLookupInquiryParameters(String parameterName, String parameterValueLocation) {
367     	// dereference literal values by simply trimming of the prefix
368     	if (parameterValueLocation.startsWith(literalPrefixAndDelimiter)) {
369     		return parameterValueLocation.substring(literalPrefixAndDelimiter.length());
370     	}
371 
372     	Object value = ObjectUtils.getPropertyValue(this, parameterValueLocation);
373 		if (value == null) {
374 			return null;
375 		}
376 		if (value instanceof String) {
377 			return (String) value;
378 		}
379 		Formatter formatter = Formatter.getFormatter(value.getClass());
380 		return (String) formatter.format(value);	
381     }
382 
383 	/**
384 	 * This overridden method ...
385 	 * 
386 	 * @see org.kuali.rice.krad.web.struts.pojo.PojoFormBase#shouldPropertyBePopulatedInForm(java.lang.String, javax.servlet.http.HttpServletRequest)
387 	 */
388 	@Override
389 	public boolean shouldPropertyBePopulatedInForm(
390 			String requestParameterName, HttpServletRequest request) {
391 		if (requestParameterName.startsWith(KRADConstants.TAB_STATES)) {
392 			return true;
393 		}
394 		
395 		if (requestParameterName.equals(KRADConstants.DISPATCH_REQUEST_PARAMETER)) {
396 			String methodToCallParameterName = request.getParameter(KRADConstants.DISPATCH_REQUEST_PARAMETER);
397 			if(StringUtils.equals(methodToCallParameterName, KRADConstants.RETURN_METHOD_TO_CALL)){
398 				return true;
399 			}
400 		}
401 		
402 		return super.shouldPropertyBePopulatedInForm(requestParameterName, request);
403 	}
404     
405     public boolean shouldMethodToCallParameterBeUsed(String methodToCallParameterName, String methodToCallParameterValue, HttpServletRequest request) {
406     	if ("GET".equalsIgnoreCase(request.getMethod())) {
407     		return true;
408     	}
409     	if (shouldPropertyBePopulatedInForm(methodToCallParameterName, request)) {
410     		return true;
411     	}
412     	if (methodToCallParameterName != null && WebUtils.endsWithCoordinates(methodToCallParameterName)) {
413     		methodToCallParameterName = methodToCallParameterName.substring(0, WebUtils.getIndexOfCoordinateExtension(methodToCallParameterName));
414         	if (shouldPropertyBePopulatedInForm(methodToCallParameterName, request)) {
415         		return true;
416         	}
417     	}
418     	if (KRADConstants.METHOD_TO_CALL_PATH.equals(methodToCallParameterName)) {
419     		if (shouldPropertyBePopulatedInForm(methodToCallParameterValue, request)) {
420     			return true;
421     		}
422     		if (methodToCallParameterValue != null && WebUtils.endsWithCoordinates(methodToCallParameterName)) {
423     			methodToCallParameterValue = methodToCallParameterValue.substring(0, WebUtils
424                         .getIndexOfCoordinateExtension(methodToCallParameterName));
425     			if (shouldPropertyBePopulatedInForm(methodToCallParameterValue, request)) {
426         			return true;
427         		}
428     		}
429     	}
430     	return false;
431     }
432 
433 	/**
434 	 * @see org.kuali.rice.krad.web.struts.pojo.PojoFormBase#clearEditablePropertyInformation()
435 	 */
436 	@Override
437 	public void clearEditablePropertyInformation() {
438 		super.clearEditablePropertyInformation();
439 	}
440 	
441 	public void setDerivedValuesOnForm(HttpServletRequest request) {
442 	}
443 
444 	/**
445 	 * @see org.apache.struts.action.ActionForm#reset(org.apache.struts.action.ActionMapping, javax.servlet.http.HttpServletRequest)
446 	 */
447 	@Override
448 	public void reset(ActionMapping mapping, HttpServletRequest request) {
449 		super.reset(mapping, request);
450 		if (extraButtons != null) {
451 			extraButtons.clear();
452 		}
453 		//fieldNameToFocusOnAfterSubmit = "";
454 		clearDisplayedMessages();
455 	}
456 
457 	/**
458 	 * @see org.apache.struts.action.ActionForm#reset(org.apache.struts.action.ActionMapping, javax.servlet.ServletRequest)
459 	 */
460 	@Override
461 	public void reset(ActionMapping mapping, ServletRequest request) {
462 		super.reset(mapping, request);
463 		if (extraButtons != null) {
464 			extraButtons.clear();
465 		}
466 		//fieldNameToFocusOnAfterSubmit = "";
467 		clearDisplayedMessages();
468 	}
469 	
470 	private void clearDisplayedMessages() {
471 		if (displayedErrors != null) {
472 			displayedErrors.clear();
473 		}
474 		if (displayedWarnings != null) {
475 			displayedWarnings.clear();
476 		}
477 		if (displayedInfo != null) {
478 			displayedInfo.clear();
479 		}
480 	}
481 	
482     /**
483 	 * @return the backLocation
484 	 */
485 	public String getBackLocation() {
486 		return this.backLocation;
487 	}
488 
489 	/**
490 	 * @param backLocation the backLocation to set
491 	 */
492 	public void setBackLocation(String backLocation) {
493 		this.backLocation = backLocation;
494 	}
495 
496 }