View Javadoc

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