View Javadoc

1   /**
2    * Copyright 2005-2013 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     	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 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 }