package hirondelle.web4j.model;

import java.util.Locale;
import java.util.TimeZone;

import hirondelle.web4j.model.ModelCtorException;

/**
 Convert request parameters into common 'building block' objects.
 
 <P>See {@link hirondelle.web4j.BuildImpl} for important information on how this item is configured. 
 {@link hirondelle.web4j.BuildImpl#forConvertParam()} 
 returns the configured implementation of this interface.
 
<h3> <a name="BuildingBlock"></a>Building Block Classes</h3>
 Here, a <em>building block</em> class is one of the 'base' objects from which Model
 Objects can in turn be built - <tt>Integer</tt>, <tt>BigDecimal</tt>, <tt>Date</tt>,
 and so on. {@link #isSupported(Class)} defines which classes are supported as 
 building block classes, and {@link #convert(String, Class, Locale, TimeZone)} defines 
 how to construct them from request parameters.
 
 <P>{@link ConvertParamImpl} is provided as a default implementation, and is likely
 suitable for many applications.
 
 <P>
 In addition, implementations may optionally choose to apply <em>universal pre-processing</em> 
 for Strings. For example, an implementation may decide to trim all Strings, or to force capitalization for 
 all Strings. Such policies may be centralized here, by including them in the implementation of 
 {@link #filter(String)} or {@link #convert(String, Class, Locale, TimeZone)}.
*/
public interface ConvertParam {

  /**
   Determine if <tt>aTargetClass</tt> is a supported <a href="#BuildingBlock">building block</a> class.
   
   <P>If <tt>aTargetClass</tt> is supported, then an underlying request parameter can be converted into 
   an object of that class.
   
   <P>The framework will always call this method first, before calling the other methods in
   this interface. 
  */
  boolean isSupported(Class<?> aTargetClass);

  /**
   Apply a policy for parameter values which are <tt>null</tt>, empty, or equal to
   <tt>IgnorableParamValue</tt> in <tt>web.xml</tt>.
   <P>
   When a 'blank' form is submitted, items are not treated in a
   uniform manner. For example, a popular browser exhibits this behavior :
   <ul>
   <li>blank text area : param submitted, empty <tt>String</tt>
   <li>radio button, with none selected : no param submitted (<tt>null</tt>)
   <li>checkbox, unselected : no param submitted (<tt>null</tt>)
   <li>drop-down selection, with first pre-selected by browser : param submitted, with value
   </ul>
   <P>
   Moreover, the W3C <a href=http://www.w3.org/TR/html4/interact/forms.html#successful-controls>spec</a> seems
   to allow for some ambiguity in what exactly is posted, so the above behavior may not be
   seen for all browsers.
   
   <P>This method is used to impose uniformity upon all such 'blank' items.
   
   <P><span class="highlight">This method can return <tt>null</tt>. Any non-<tt>null</tt> 
   values returned by this method must have content.</span> (That is, an implementation cannot return a 
   <tt>String</tt> which, when trimmed, is empty.)
    
   @param aRawParamValue the raw, unchanged parameter value, as submitted in the underlying request.
  */
  String filter(String aRawParamValue);

  /**
   Convert a request parameter value into a <a href="#BuildingBlock">building block</a> object.
   <P>
   The value passed to this method is first <em>filtered</em>, using {@link #filter(String)}.
   <span class="highlight">Implementations must throw a {@link ModelCtorException} when a parsing problem occurs</span>.
   <P>
   @param aFilteredParamValue parameter value as returned by {@link #filter(String)}
   @param aSupportedTargetClass supported target building block class in a Model Object constructor
   @param aLocale {@link Locale} returned by the implementation of {@link hirondelle.web4j.request.LocaleSource}
   @param aTimeZone {@link TimeZone} returned by the implementation of {@link hirondelle.web4j.request.TimeZoneSource}
  */
  <T> T convert(String aFilteredParamValue, Class<T> aSupportedTargetClass, Locale aLocale, TimeZone aTimeZone) throws ModelCtorException;
}
