Coverage Report - org.kuali.rice.kns.web.struts.pojo.PojoFormBase
 
Classes in this File Line Coverage Branch Coverage Complexity
PojoFormBase
0%
0/198
0%
0/64
2.044
 
 1  
 /*
 2  
  * Copyright 2004 Jonathan M. Lehr
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
 5  
  * You may obtain a copy of the License at
 6  
  *
 7  
  * http://www.apache.org/licenses/LICENSE-2.0
 8  
  *
 9  
  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
 10  
  * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
 11  
  * governing permissions and limitations under the License.
 12  
  * 
 13  
  * MODIFIED BY THE KUALI FOUNDATION
 14  
  */
 15  
  
 16  
 // begin Kuali Foundation modification
 17  
 package org.kuali.rice.kns.web.struts.pojo;
 18  
 
 19  
 import java.lang.reflect.InvocationTargetException;
 20  
 import java.util.ArrayList;
 21  
 import java.util.Collections;
 22  
 import java.util.Enumeration;
 23  
 import java.util.HashMap;
 24  
 import java.util.HashSet;
 25  
 import java.util.Hashtable;
 26  
 import java.util.Iterator;
 27  
 import java.util.List;
 28  
 import java.util.Map;
 29  
 import java.util.Set;
 30  
 
 31  
 import javax.servlet.http.HttpServletRequest;
 32  
 
 33  
 import org.apache.commons.beanutils.PropertyUtils;
 34  
 import org.apache.commons.lang.StringUtils;
 35  
 import org.apache.log4j.Logger;
 36  
 import org.apache.struts.action.ActionForm;
 37  
 import org.apache.struts.upload.MultipartRequestHandler;
 38  
 import org.apache.struts.upload.MultipartRequestWrapper;
 39  
 import org.kuali.rice.kns.exception.ValidationException;
 40  
 import org.kuali.rice.kns.service.KNSServiceLocator;
 41  
 import org.kuali.rice.kns.util.GlobalVariables;
 42  
 import org.kuali.rice.kns.util.KNSConstants;
 43  
 import org.kuali.rice.kns.util.ObjectUtils;
 44  
 import org.kuali.rice.kns.util.Timer;
 45  
 import org.kuali.rice.kns.util.WebUtils;
 46  
 import org.kuali.rice.kns.web.format.EncryptionFormatter;
 47  
 import org.kuali.rice.kns.web.format.FormatException;
 48  
 import org.kuali.rice.kns.web.format.Formatter;
 49  
 
 50  
 /**
 51  
  * This class is the base form which implements the PojoForm interface.
 52  
  * Kuali Foundation modification: javadoc comments changed
 53  
  */
 54  
 // begin Kuali Foundation modification: this class was named SLActionForm
 55  0
 public class PojoFormBase extends ActionForm implements PojoForm {
 56  
     private static final long serialVersionUID = 1L;
 57  
     
 58  
     // begin Kuali Foundation modification
 59  0
     private static final Logger LOG = Logger.getLogger(PojoFormBase.class);
 60  
     
 61  
     private static final String PREVIOUS_REQUEST_EDITABLE_PROPERTIES_GUID = "editablePropertiesGuid";
 62  
 
 63  
         // removed member variables: cachedActionErrors, coder, errorInfo, fieldOrder, formConfig, HEADING_KEY, IGNORED_KEYS,
 64  
         //     invalidValueKeys, logger, messageResourceKey, messageResources, padNonRequiredFields, valueBinder
 65  
          
 66  
     static final String CREATE_ERR_MSG = "Can't create formatter for keypath ";
 67  
     static final String CONVERT_ERR_MSG = "Can't convert value for keypath: ";
 68  
 
 69  0
     static Map classCache = Collections.synchronizedMap(new HashMap());
 70  
 
 71  0
     private Map unconvertedValues = new HashMap();
 72  0
     private List unknownKeys = new ArrayList();
 73  0
     private Map formatterTypes = new HashMap();
 74  0
     private List<String> maxUploadFileSizes = new ArrayList<String>();
 75  0
     private Set<String> editableProperties = new HashSet<String>();
 76  0
     protected Set<String> requiredNonEditableProperties = new HashSet<String>();
 77  
     private String strutsActionMappingScope; 
 78  0
     private boolean isNewForm = true;
 79  
     
 80  
     private String populateEditablePropertiesGuid;
 81  
     private String actionEditablePropertiesGuid;
 82  
 
 83  
     // removed methods: PojoFormBase()/SLActionForm(), addFormLevelMessageInfo, addGlobalMessage, addIgnoredKey, addIgnoredKeys, addLengthValidation, addMessageIfAbsent
 84  
     //     addPatternValidation, addPropertyValidationRules, addRangeValidation, addRequiredField, addRequiredFields
 85  
     //     addUnknownKey, addValidationRule(String, ValidationRule), addValidationRule(ValidationRule), cachedActionErrors, clearIgnoredKeys,
 86  
     //     clearUnknownKeys, clearValidationErrors, coalesceMessageArgs, containsKey, convertValue, createActionMessage, createMessageResourcesIfNecessary, fieldOrder, fieldValidationRuleOrder,
 87  
     //     formatMessage, formatMessageArgs, formatterSettingsForKeypath, formatterTypeForKeypath, formBeanConfigForKey, formConfig, formValidationRuleOrder,
 88  
     //     generateErrorMessages, getActionErrors, getActionMessages, getErrorMessages, getFieldLabel, getFormatterTypes, getGlobalMessages, getIgnoredKeys, getInvalidValueKeys, getLabels, getLengthValidations, getLocale,
 89  
     //     getMultipartRequestParameters, getPadNonRequiredFields, 
 90  
     //     getPatternValidations, getPropertyConfig, getRangeValidations, getRequiredFields, hasErrorMessageForKey, hasErrors, hasFormatterForKeypath,
 91  
     //     hasGlobalMessageForKey, isMultipart, messageForKey, messageForRule, messageInfoForRule, messageResourcesConfigForKey, messageResourcesKey, messageResourcesPath,
 92  
     //     messagesForFormLevelRule, messagesForKey, moduleConfigForRequest, removeIgnoredKey, removePropertyConfig,
 93  
     //     renderErrorMessages, renderGlobalMessages, renderMessages, setFieldLabel, setFieldOrder, setFormatterType(String, Class, Map)
 94  
     //     setFormConfig, setInvalidValueKeys, setLengthValidations, setMessageResourceKey,setPadNonRequiredFields, setPatternValidations, setPropertyConfig, setRangeValidations,
 95  
     //     setRequiredFields, setValueBinder, shouldFormat, validate, validateForm, validateLength, validatePattern, validateProperty, validateRange, validateRequestValues, validateRequired, valueBinder
 96  
 
 97  
         // end Kuali Foundation modification
 98  
         
 99  
 
 100  
         // begin Kuali Foundation modification
 101  
     /**
 102  
      * Method is called after parameters from a multipart request have been made accessible to request.getParameter calls, but
 103  
      * before request parameter values are used to instantiate and populate business objects. Important note: parameters in the
 104  
      * given Map which were created from a multipart-encoded parameter will, apparently, be stored in the given Map as String[]
 105  
      * instead of as String.
 106  
      *
 107  
      * @param requestParameters
 108  
      */
 109  
 
 110  
     public void postprocessRequestParameters(Map requestParameters) {
 111  
         // do nothing
 112  0
     }
 113  
     // end Kuali Foundation modification
 114  
 
 115  
  
 116  
 
 117  
     /**
 118  
      * Populates the form with values from the current request. Uses instances of Formatter to convert strings to the Java types of
 119  
      * the properties to which they are bound. Values that can't be converted are cached in a map of unconverted values. Returns an
 120  
      * ActionErrors containing ActionMessage instances for each conversion error that occured, if any.
 121  
      */
 122  
     public void populate(HttpServletRequest request) {
 123  0
         Timer t0 = new Timer("PojoFormBase.populate");
 124  0
         unconvertedValues.clear();
 125  0
         unknownKeys = new ArrayList();
 126  0
         addRequiredNonEditableProperties();
 127  0
         Map params = request.getParameterMap();
 128  
 
 129  0
         String contentType = request.getContentType();
 130  0
         String method = request.getMethod();
 131  
 
 132  0
         if ("POST".equalsIgnoreCase(method) && contentType != null && contentType.startsWith("multipart/form-data")) {
 133  0
             Map fileElements = (HashMap)request.getAttribute(KNSConstants.UPLOADED_FILE_REQUEST_ATTRIBUTE_KEY);
 134  0
             Enumeration names = Collections.enumeration(fileElements.keySet());
 135  0
             while (names.hasMoreElements()) {
 136  0
                 String name = (String) names.nextElement();
 137  0
                 params.put(name, fileElements.get(name));
 138  0
             }
 139  
         }
 140  
 
 141  0
         postprocessRequestParameters(params);
 142  
 
 143  
 
 144  
         /**
 145  
          * Iterate through request parameters, if parameter matches a form variable, get the property type, formatter and convert,
 146  
          * if not add to the unknowKeys map.
 147  
          */
 148  0
         for (Iterator iter = params.keySet().iterator(); iter.hasNext();) {
 149  0
             String keypath = (String) iter.next();
 150  0
             if (shouldPropertyBePopulatedInForm(keypath, request)) {
 151  0
                     Object param = params.get(keypath);
 152  
                     //LOG.debug("(keypath,paramType)=(" + keypath + "," + param.getClass().getName() + ")");
 153  
         
 154  0
                     populateForProperty(keypath, param, params);
 155  
             }
 156  0
         }
 157  0
         this.registerIsNewForm(false);
 158  0
         t0.log();
 159  0
     }
 160  
 
 161  
 
 162  
 
 163  
         /**
 164  
          * Populates a given parameter value into the given property path
 165  
          * @param paramPath the path to a property within the form
 166  
          * @param paramValue the value of that property
 167  
          * @param params the Map of parameters from the request
 168  
          */
 169  
         protected void populateForProperty(String paramPath, Object paramValue,
 170  
                         Map params) {
 171  
                 // get type for property
 172  0
                 Class type = null;
 173  
                 try {
 174  
                     // TODO: see KULOWF-194
 175  
                     //testForPojoHack(this, keypath);
 176  0
                     type = getPropertyType(paramPath);
 177  
                 }
 178  0
                 catch (Exception e) {
 179  
                     // deleted redundant unknownKeys.add(keypath)
 180  0
                 }
 181  
 
 182  
                 // keypath does not match anything on form
 183  0
                 if (type == null) {
 184  0
                     unknownKeys.add(paramPath);
 185  
                 }
 186  
                 else {
 187  0
                     Formatter formatter = null;
 188  
                     try {
 189  0
                         formatter = buildFormatter(paramPath, type, params);
 190  
 
 191  0
                         ObjectUtils.setObjectProperty(formatter, this, paramPath, type, paramValue);
 192  
                             }
 193  0
                     catch (FormatException e1) {
 194  0
                         GlobalVariables.getMessageMap().putError(paramPath, e1.getErrorKey(), e1.getErrorArgs());
 195  0
                         cacheUnconvertedValue(paramPath, paramValue);
 196  
                     }
 197  0
                     catch (InvocationTargetException e1) {
 198  0
                         if (e1.getTargetException().getClass().equals(FormatException.class)) {
 199  
                             // Handle occasional case where FormatException is wrapped in an InvocationTargetException
 200  0
                             FormatException formatException = (FormatException) e1.getTargetException();
 201  0
                             GlobalVariables.getMessageMap().putError(paramPath, formatException.getErrorKey(), formatException.getErrorArgs());
 202  0
                             cacheUnconvertedValue(paramPath, paramValue);
 203  0
                         }
 204  
                         else {
 205  0
                             LOG.error("Error occurred in populate " + e1.getMessage());
 206  0
                             throw new RuntimeException(e1.getMessage(), e1);
 207  
                         }
 208  
                     }
 209  0
                     catch (Exception e1) {
 210  0
                         LOG.error("Error occurred in populate " + e1.getMessage());
 211  0
                             LOG.error("FormClass:       " + this.getClass().getName() );
 212  0
                             LOG.error("keypath:         " + paramPath );
 213  0
                             LOG.error("Detected Type:   " + type.getName() );
 214  0
                             LOG.error( "Value:          " + paramValue );
 215  0
                             if ( paramValue != null ) {
 216  0
                                         LOG.error( "Value Class:    " + paramValue.getClass().getName() );
 217  
                             }
 218  0
                         throw new RuntimeException(e1.getMessage(), e1);
 219  0
                     }
 220  
                 }
 221  0
         }
 222  
 
 223  
         // begin Kuali Foundation modification
 224  
     private Formatter buildFormatter(String keypath, Class propertyType, Map requestParams) {
 225  0
         Formatter formatter = buildFormatterForKeypath(keypath, propertyType, requestParams);
 226  0
         if (formatter == null) {
 227  0
             formatter = buildFormatterForType(propertyType);
 228  
         }
 229  0
         return formatter;
 230  
     }
 231  
     // end Kuali Foundation modification
 232  
 
 233  
         // begin Kuali Foundation modification
 234  
     private Formatter buildFormatterForKeypath(String keypath, Class propertyType, Map requestParams) {
 235  0
         Formatter formatter = null;
 236  
 
 237  0
         Class formatterClass = formatterClassForKeypath(keypath);
 238  
 
 239  0
         if (formatterClass != null) {
 240  
             try {
 241  0
                 formatter = (Formatter) formatterClass.newInstance();
 242  
             }
 243  0
             catch (InstantiationException e) {
 244  0
                 throw new FormatException("unable to instantiate formatter class '" + formatterClass.getName() + "'", e);
 245  
             }
 246  0
             catch (IllegalAccessException e) {
 247  0
                 throw new FormatException("unable to access formatter class '" + formatterClass.getName() + "'", e);
 248  0
             }
 249  0
             formatter.setPropertyType(propertyType);
 250  
         }
 251  0
         return formatter;
 252  
     }
 253  
     // end Kuali Foundation modification
 254  
 
 255  
         // begin Kuali Foundation modification
 256  
     private Formatter buildFormatterForType(Class propertyType) {
 257  0
         Formatter formatter = null;
 258  
 
 259  0
         if (Formatter.findFormatter(propertyType) != null) {
 260  0
             formatter = Formatter.getFormatter(propertyType);
 261  
         }
 262  0
         return formatter;
 263  
     }
 264  
     // end Kuali Foundation modification
 265  
 
 266  
         // begin Kuali Foundation modification
 267  
     /**
 268  
      * <p>
 269  
      * Create a <code>Map</code> containing all of the parameters supplied for a multipart request, keyed by parameter name. In
 270  
      * addition to text and file elements from the multipart body, query string parameters are included as well.
 271  
      * </p>
 272  
      *
 273  
      * @param request The (wrapped) HTTP request whose parameters are to be added to the map.
 274  
      * @param multipartHandler The multipart handler used to parse the request.
 275  
      *
 276  
      * @return the map containing all parameters for this multipart request.
 277  
      */
 278  
     private static Map getAllParametersForMultipartRequest(HttpServletRequest request, MultipartRequestHandler multipartHandler) {
 279  0
         Timer t0 = new Timer("PojoFormBase.getAllParametersForMultipartRequest");
 280  
 
 281  0
         Map parameters = new HashMap();
 282  0
         Hashtable elements = multipartHandler.getAllElements();
 283  0
         Enumeration e = elements.keys();
 284  0
         while (e.hasMoreElements()) {
 285  0
             String key = (String) e.nextElement();
 286  0
             parameters.put(key, elements.get(key));
 287  0
         }
 288  
 
 289  0
         if (request instanceof MultipartRequestWrapper) {
 290  0
             request = ((MultipartRequestWrapper) request).getRequest();
 291  0
             e = request.getParameterNames();
 292  0
             while (e.hasMoreElements()) {
 293  0
                 String key = (String) e.nextElement();
 294  0
                 parameters.put(key, request.getParameterValues(key));
 295  0
             }
 296  
         }
 297  
         else {
 298  0
             LOG.debug("Gathering multipart parameters for unwrapped request");
 299  
         }
 300  
 
 301  0
         t0.log();
 302  0
         return parameters;
 303  
     }
 304  
     // end Kuali Foundation modification
 305  
 
 306  
     /**
 307  
      * Delegates to {@link PropertyUtils#getPropertyType(Object, String)}to look up the property type for the provided keypath.
 308  
      * Caches the resulting class so that subsequent lookups for the same keypath can be satisfied by looking in the cache.
 309  
      *
 310  
      * @throws NoSuchMethodException
 311  
      * @throws InvocationTargetException
 312  
      * @throws IllegalAccessException
 313  
      */
 314  
     protected Class getPropertyType(String keypath) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
 315  0
         Map propertyTypes = (Map) classCache.get(getClass());
 316  0
         if (propertyTypes == null) {
 317  0
             propertyTypes = new HashMap();
 318  0
             classCache.put(getClass(), propertyTypes);
 319  
         }
 320  
 
 321  
         // if type has not been retrieve previousely, use ObjectUtils to get type
 322  0
         if (!propertyTypes.containsKey(keypath)) {
 323  0
             Class type = ObjectUtils.easyGetPropertyType(this, keypath);
 324  0
             propertyTypes.put(keypath, type);
 325  
         }
 326  
 
 327  0
         Class propertyType = (Class) propertyTypes.get(keypath);
 328  0
         return propertyType;
 329  
     }
 330  
 
 331  
 
 332  
     /**
 333  
      * Retrieves a formatter for the keypath and property type.
 334  
      *
 335  
      * @param keypath
 336  
      * @param propertyType
 337  
      * @return
 338  
      */
 339  
     protected Formatter getFormatter(String keypath, Class propertyType) {
 340  
         // check for a formatter associated with the keypath
 341  0
         Class type = formatterClassForKeypath(keypath);
 342  
 
 343  
         Formatter formatter;
 344  0
         if (type == null) {
 345  
             // retrieve formatter based on property type
 346  0
             formatter = Formatter.getFormatter(propertyType);
 347  
         }
 348  
         else {
 349  
             try {
 350  0
                 formatter = (Formatter) type.newInstance();
 351  0
                 formatter.setPropertyType(propertyType);
 352  
             }
 353  0
             catch (Exception e) {
 354  0
                 throw new ValidationException(CREATE_ERR_MSG, e);
 355  0
             }
 356  
         }
 357  0
         return formatter;
 358  
     }
 359  
 
 360  
 
 361  
         // begin Kuali Foundation modification
 362  
     /**
 363  
      * Retrieves any formatters associated specially with the keypath.
 364  
      *
 365  
      * @param keypath
 366  
      * @return
 367  
      */
 368  
     protected Class formatterClassForKeypath(String keypath) {
 369  
         // remove traces of array and map indices from the incoming keypath
 370  0
         String indexlessKey = keypath.replaceAll("(\\[[0-9]*+\\]|\\(.*?\\))", "");
 371  
 
 372  0
         return (Class)formatterTypes.get( indexlessKey );
 373  
     }
 374  
     // end Kuali Foundation modification
 375  
 
 376  
     /**
 377  
      * Tries to format the provided value by passing it to a suitable {@link Formatter}. Adds an ActionMessage to the ActionErrors
 378  
      * in the request if a FormatException is thrown.
 379  
      * <p>
 380  
      * Caution should be used when invoking this method. It should never be called prior to {@link #populate(HttpServletRequest)}
 381  
      * because the cached request reference could be stale.
 382  
      */
 383  
     public Object formatValue(Object value, String keypath, Class type) {
 384  
 
 385  0
         Formatter formatter = getFormatter(keypath, type);
 386  0
         if ( LOG.isDebugEnabled() ) {
 387  0
             LOG.debug("formatValue (value,keypath,type) = (" + value + "," + keypath + "," + type.getName() + ")");
 388  
         }
 389  
 
 390  
         try {
 391  0
             return Formatter.isSupportedType(type) ? formatter.formatForPresentation(value) : value;
 392  
         }
 393  0
         catch (FormatException e) {
 394  0
             GlobalVariables.getMessageMap().putError(keypath, e.getErrorKey(), e.getErrorArgs());
 395  0
             return value.toString();
 396  
         }
 397  
     }
 398  
 
 399  
     /**
 400  
      * Sets the Formatter class to use for a given keypath. This class will be used by the form instead of the one returned by calls
 401  
      * to {@link Formatter#getFormatter(Class)}, which is the default mechanism.
 402  
      */
 403  
     public void setFormatterType(String keypath, Class type) {
 404  0
         formatterTypes.put(keypath, type);
 405  0
     }
 406  
 
 407  
     public Map getUnconvertedValues() {
 408  0
         return unconvertedValues;
 409  
     }
 410  
 
 411  
     public void setUnconvertedValues(Map unconvertedValues) {
 412  0
         this.unconvertedValues = unconvertedValues;
 413  0
     }
 414  
 
 415  
     protected List getUnknownKeys() {
 416  0
         return unknownKeys;
 417  
     }
 418  
 
 419  
     protected void cacheUnconvertedValue(String key, Object value) {
 420  0
         Class type = value.getClass();
 421  0
         if (type.isArray()) {
 422  0
             value = Formatter.isEmptyValue(value) ? null : ((Object[]) value)[0];
 423  
         }
 424  
 
 425  0
         unconvertedValues.put(key, value);
 426  0
     }
 427  
 
 428  
         // begin Kuali Foundation modification
 429  
     public void processValidationFail() {
 430  
         // do nothing - subclasses can implement this if they want to.
 431  0
     }
 432  
     // end Kuali Foundation modification
 433  
 
 434  
 
 435  
         // begin Kuali Foundation modification
 436  
     /**
 437  
      * Gets the formatterTypes attribute.
 438  
      * 
 439  
      * @return Returns the formatterTypes.
 440  
      */
 441  
     public Map getFormatterTypes() {
 442  0
         return formatterTypes;
 443  
     }
 444  
     // end Kuali Foundation modification
 445  
 
 446  
 
 447  
         // begin Kuali Foundation modification
 448  
     /**
 449  
      * Sets the formatterTypes attribute value.
 450  
      * @param formatterTypes The formatterTypes to set.
 451  
      */
 452  
     public void setFormatterTypes(Map formatterTypes) {
 453  0
         this.formatterTypes = formatterTypes;
 454  0
     }
 455  
     // end Kuali Foundation modification
 456  
 
 457  
 
 458  
         // begin Kuali Foundation modification
 459  
     /**
 460  
      * Adds the given string as a maximum size to the form.  It will be used if a file upload is used.
 461  
      * 
 462  
      * @param sizeString
 463  
      */
 464  
     protected final void addMaxUploadSize( String sizeString ) {
 465  0
         maxUploadFileSizes.add( sizeString );
 466  0
     }
 467  
 
 468  
     /**
 469  
      * Initializes the list of max upload sizes if necessary. 
 470  
      *
 471  
      */
 472  
     protected final void initMaxUploadSizes() {
 473  0
             if ( maxUploadFileSizes.isEmpty() ) {
 474  0
                 customInitMaxUploadSizes();
 475  
                 // if it's still empty, add the default
 476  0
                 if ( maxUploadFileSizes.isEmpty() ) {
 477  0
                     addMaxUploadSize(KNSServiceLocator.getParameterService().getParameterValue(KNSConstants.KNS_NAMESPACE, KNSConstants.DetailTypes.ALL_DETAIL_TYPE, KNSConstants.MAX_UPLOAD_SIZE_PARM_NM));
 478  
                 }
 479  
             }        
 480  0
     }
 481  
     
 482  
     /**
 483  
      * Subclasses can override this to add their own max upload size to the list.  Only the largest passed will be used.
 484  
      *
 485  
      */
 486  
     protected void customInitMaxUploadSizes() {
 487  
         // nothing here
 488  0
     }
 489  
     
 490  
     public final List<String> getMaxUploadSizes() {
 491  0
         initMaxUploadSizes();
 492  
         
 493  0
         return maxUploadFileSizes;
 494  
     }
 495  
     
 496  
     public void registerEditableProperty(String editablePropertyName){
 497  0
             if ( LOG.isDebugEnabled() ) {
 498  0
                     LOG.debug( "KualiSessionId: " + GlobalVariables.getUserSession().getKualiSessionId() + " -- Registering Property: " + editablePropertyName );
 499  
             }
 500  0
             editableProperties.add(editablePropertyName);
 501  0
     }
 502  
     
 503  
     public void registerRequiredNonEditableProperty(String requiredNonEditableProperty) {
 504  0
             requiredNonEditableProperties.add(requiredNonEditableProperty);
 505  0
     }
 506  
     
 507  
     public void clearEditablePropertyInformation(){
 508  0
             if ( LOG.isDebugEnabled() ) {
 509  0
                     LOG.debug( "KualiSessionId: " + GlobalVariables.getUserSession().getKualiSessionId() + " -- Clearing Editable Properties" );
 510  
             }
 511  0
             editableProperties = new HashSet<String>();
 512  0
     }
 513  
     
 514  
     public Set<String> getEditableProperties(){
 515  0
             return editableProperties;
 516  
     }
 517  
  
 518  
     public boolean isPropertyEditable(String propertyName) {
 519  0
             final Set<String> populateEditableProperties = getPopulateEditableProperties();
 520  0
         return WebUtils.isPropertyEditable(populateEditableProperties, propertyName);
 521  
     }
 522  
     
 523  
     /***
 524  
      * @see org.kuali.rice.kns.web.struts.pojo.PojoForm#addRequiredNonEditableProperties()
 525  
      */
 526  
     public void addRequiredNonEditableProperties(){
 527  0
     }
 528  
     
 529  
     public boolean isPropertyNonEditableButRequired(String propertyName) {
 530  0
         return WebUtils.isPropertyEditable(requiredNonEditableProperties, propertyName);
 531  
     }
 532  
     
 533  
     protected String getParameter(HttpServletRequest request, String parameterName){
 534  0
             return request.getParameter(parameterName);
 535  
     }
 536  
     
 537  
     protected String[] getParameterValues(HttpServletRequest request, String parameterName){
 538  0
             return request.getParameterValues(parameterName);
 539  
     }
 540  
     
 541  
     public Set<String> getRequiredNonEditableProperties(){
 542  0
             return requiredNonEditableProperties;
 543  
     }
 544  
     
 545  
         /**
 546  
          * @see PojoForm#registerStrutsActionMappingScope(String)
 547  
          */
 548  
         public void registerStrutsActionMappingScope(String strutsActionMappingScope) {
 549  0
                 this.strutsActionMappingScope = strutsActionMappingScope;
 550  0
         }
 551  
         
 552  
         public String getStrutsActionMappingScope() {
 553  0
                 return strutsActionMappingScope;
 554  
         }
 555  
         
 556  
         /**
 557  
          * @see PojoForm#registerStrutsActionMappingScope(String)
 558  
          */
 559  
         public void registerIsNewForm(boolean isNewForm) {
 560  0
                 this.isNewForm = isNewForm;
 561  0
         }
 562  
         
 563  
         public boolean getIsNewForm() {
 564  0
                 return this.isNewForm;
 565  
         }
 566  
         
 567  
         
 568  
         /**
 569  
          * @see org.kuali.rice.kns.web.struts.pojo.PojoForm#shouldPropertyBePopulatedInForm(java.lang.String, javax.servlet.http.HttpServletRequest)
 570  
          */
 571  
         public boolean shouldPropertyBePopulatedInForm(String requestParameterName, HttpServletRequest request) {
 572  
                 
 573  0
                 if (requestParameterName.equals(PojoFormBase.PREVIOUS_REQUEST_EDITABLE_PROPERTIES_GUID)) {
 574  0
                         return false; // don't repopulate this
 575  
                 }
 576  0
                 else if (StringUtils.equalsIgnoreCase("session",getStrutsActionMappingScope()) && !getIsNewForm()) {
 577  0
                         return isPropertyEditable(requestParameterName) || isPropertyNonEditableButRequired(requestParameterName); 
 578  
                 }
 579  0
                 return true;
 580  
                 
 581  
         }
 582  
 
 583  
         /**
 584  
          * Base implementation that returns just "start".  sub-implementations should not add values to Set instance returned
 585  
          * by this method, and should create its own instance.
 586  
          * 
 587  
          * @see org.kuali.rice.kns.web.struts.pojo.PojoForm#getMethodToCallsToBypassSessionRetrievalForGETRequests()
 588  
          */
 589  
         public Set<String> getMethodToCallsToBypassSessionRetrievalForGETRequests() {
 590  0
                 Set<String> defaultMethodToCalls = new HashSet<String>();
 591  0
                 defaultMethodToCalls.add(KNSConstants.START_METHOD);
 592  0
                 return defaultMethodToCalls;
 593  
         }
 594  
 
 595  
 
 596  
 
 597  
         /**
 598  
          * Sets the guid to editable properties consulted during population
 599  
          * 
 600  
          * @see org.kuali.rice.kns.web.struts.pojo.PojoForm#setEditablePropertiesGuid(java.lang.String)
 601  
          */
 602  
         public void setPopulateEditablePropertiesGuid(String guid) {
 603  0
                 this.populateEditablePropertiesGuid = guid;
 604  0
         }
 605  
         
 606  
         /**
 607  
          * @return the guid for the populate editable properties
 608  
          */
 609  
         public String getPopulateEditablePropertiesGuid() {
 610  0
                 return this.populateEditablePropertiesGuid;
 611  
         }
 612  
         
 613  
         /**
 614  
          * Sets the guid of the editable properties which were registered by the action
 615  
          * @see org.kuali.rice.kns.web.struts.pojo.PojoForm#setActionEditablePropertiesGuid(java.lang.String)
 616  
          */
 617  
         public void setActionEditablePropertiesGuid(String guid) {
 618  0
                 this.actionEditablePropertiesGuid = guid;
 619  0
         }
 620  
         
 621  
         /**
 622  
          * @return the guid of the editable properties which had been registered by the action processing
 623  
          */
 624  
         public String getActionEditablePropertiesGuid() {
 625  0
                 return actionEditablePropertiesGuid;
 626  
         }
 627  
         
 628  
         /**
 629  
          * @return the editable properties to be consulted during population
 630  
          */
 631  
         public Set<String> getPopulateEditableProperties() {
 632  0
                 return GlobalVariables.getUserSession().getEditablePropertiesHistoryHolder().getEditableProperties(getPopulateEditablePropertiesGuid());
 633  
         }
 634  
         
 635  
         /**
 636  
          * Copies all editable properties in the populate editable properties to the action editable properties
 637  
          */
 638  
         public void copyPopulateEditablePropertiesToActionEditableProperties() {
 639  0
                 Set<String> populateEditableProperties = getPopulateEditableProperties();
 640  0
                 for (String property : populateEditableProperties) {
 641  0
                         registerEditableProperty(property);
 642  
                 }
 643  0
         }
 644  
         
 645  
         // end Kuali Foundation modification
 646  
 }