package org.nocket.component.form;
import org.apache.commons.lang.StringUtils;
import org.apache.wicket.Component;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.IObjectClassAwareModel;
import org.apache.wicket.util.convert.ConversionException;
import org.apache.wicket.util.convert.IConverter;
import org.apache.wicket.util.string.Strings;
import org.nocket.gen.domain.WebDomainProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* In Wicket werden Parameter bevor sie in den Setter geschrieben werden
* getrimmt und wenn es dann ein Leestring ist zu NULL gemacht. Dies ist nur
* bedingt gut. Es gibt doch Projekte, die ihre Daten, auch wenn sie schlecht
* sind, behalten wollen. Allerdings kann es sinnvoll sein einen richtigen
* Leerstring zu NULL zu wandeln. Diese EntitÀt liesst den Defaultwert fÌr das
* Verhalten aus den gengui.properties (InputStringConvertStrategy). GeÀndert
* kann die verwendete Strategie mit der Methode <code>
* setConvertInputStringModus(InputStringConvertStrategy convertInputStringModus)
* </code> FÌr die InputStringConvertStrategy gibt es folgende Möglichkeiten:<br>
* <ul>
* <li>none = keine Konvertiertung</li>
* <li>trimAndEmptyToNull = nur Leerstrings werden zu null (kein Trim)</li>
* <li>noTrimButEmptyToNull = Trimmern und danach einen Leerstring zu null
* konvertieren</li>
* </ul>
*/
public class DMDTextField<T> extends TextField<T> {
public enum InputStringConvertStrategy {
none, trimAndEmptyToNull, noTrimButEmptyToNull
}
private static final long serialVersionUID = 1L;
private boolean convertBlankInputStringToNull;
/** Log for reporting. */
private static final Logger log = LoggerFactory.getLogger(DMDTextField.class);
public DMDTextField(String id, Class<T> type) {
super(id, type);
setConvertInputStringModus(new WebDomainProperties().getInputStringConvertStrategy());
}
public DMDTextField(String id, IModel<T> model, Class<T> type) {
super(id, model, type);
setConvertInputStringModus(new WebDomainProperties().getInputStringConvertStrategy());
}
public DMDTextField(String id, IModel<T> model) {
super(id, model);
setConvertInputStringModus(new WebDomainProperties().getInputStringConvertStrategy());
}
public DMDTextField(String id) {
super(id);
setConvertInputStringModus(new WebDomainProperties().getInputStringConvertStrategy());
}
public void setConvertInputStringModus(InputStringConvertStrategy convertInputStringModus) {
if (convertInputStringModus == null || InputStringConvertStrategy.none.equals(convertInputStringModus)) {
setConvertBlankInputStringToNull(false);
setConvertEmptyInputStringToNull(false);
} else if (InputStringConvertStrategy.noTrimButEmptyToNull.equals(convertInputStringModus)) {
setConvertBlankInputStringToNull(true);
setConvertEmptyInputStringToNull(false);
} else if (InputStringConvertStrategy.trimAndEmptyToNull.equals(convertInputStringModus)) {
setConvertBlankInputStringToNull(false);
setConvertEmptyInputStringToNull(true);
}
}
public void setConvertBlankInputStringToNull(boolean trimInputString) {
this.convertBlankInputStringToNull = trimInputString;
}
/**
* Subclasses should overwrite this if the conversion is not done through
* the type field and the {@link IConverter}. <strong>WARNING: this method
* may be removed in future versions.</strong>
*
* If conversion fails then a ConversionException should be thrown
*
* @param value
* The value can be the getInput() or through a cookie
*
* @return The converted value. default returns just the given value
* @throws ConversionException
* If input can't be converted
*/
@SuppressWarnings("unchecked")
protected T convertValue(String[] value) throws ConversionException
{
if (value == null || value.length <= 0 || value[0] == null) {
return null;
}
if (!convertBlankInputStringToNull) {
return (T) (value[0].length() != 0 ? value[0] : null);
}
return (T) trim(value[0]);
}
/**
* Convert the input respecting the flag convertEmptyInputStringToNull.
* Subclasses that override this method should test this flag also.
*
* @see org.apache.wicket.markup.html.form.FormComponent#convertInput()
*/
@Override
protected void convertInput()
{
// Stateless forms don't have to be rendered first, convertInput could be called before
// onBeforeRender calling resolve type here again to check if the type is correctly set.
resolveType();
String[] value = getInputAsArray();
String tmp = value != null && value.length > 0 ? value[0] : null;
if (convertBlankInputStringToNull && StringUtils.isBlank(tmp))
{
setConvertedInput(null);
}
else if (getConvertEmptyInputStringToNull() && Strings.isEmpty(tmp))
{
setConvertedInput(null);
}
else
{
super.convertInput();
}
}
// Kopie der Wicket-Methode resolveType aus AbstractTextComponent, die private ist.
private static final int TYPE_RESOLVED = Component.FLAG_RESERVED4;
/**
* Kopie der Wicket-Methode resolveType aus AbstractTextComponent, die
* private ist.
*/
private void resolveType()
{
if (!getFlag(TYPE_RESOLVED) && getType() == null)
{
Class<?> type = getModelType(getDefaultModel());
setType(type);
setFlag(TYPE_RESOLVED, true);
}
}
/**
* Kopie der Wicket-Methode resolveType aus AbstractTextComponent, die
* private ist.
*
* @param model
* @return the type of the model object or <code>null</code>
*/
private Class<?> getModelType(IModel<?> model)
{
if (model instanceof IObjectClassAwareModel)
{
Class<?> objectClass = ((IObjectClassAwareModel<?>) model).getObjectClass();
if (objectClass == null)
{
log.warn("Couldn't resolve model type of " + model + " for " + this +
", please set the type yourself.");
}
return objectClass;
}
else
{
return null;
}
}
protected boolean shouldTrimInput()
{
return getConvertEmptyInputStringToNull();
}
}