📄 formcomponent.java
字号:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.apache.wicket.markup.html.form;import java.text.Format;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Collections;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Locale;import java.util.Map;import org.apache.wicket.Application;import org.apache.wicket.Component;import org.apache.wicket.Localizer;import org.apache.wicket.MarkupContainer;import org.apache.wicket.Page;import org.apache.wicket.WicketRuntimeException;import org.apache.wicket.markup.ComponentTag;import org.apache.wicket.markup.html.border.Border;import org.apache.wicket.model.IModel;import org.apache.wicket.util.convert.ConversionException;import org.apache.wicket.util.convert.IConverter;import org.apache.wicket.util.lang.Classes;import org.apache.wicket.util.string.PrependingStringBuffer;import org.apache.wicket.util.string.StringList;import org.apache.wicket.util.string.Strings;import org.apache.wicket.util.string.interpolator.MapVariableInterpolator;import org.apache.wicket.validation.IErrorMessageSource;import org.apache.wicket.validation.INullAcceptingValidator;import org.apache.wicket.validation.IValidatable;import org.apache.wicket.validation.IValidationError;import org.apache.wicket.validation.IValidator;import org.apache.wicket.validation.IValidatorAddListener;import org.apache.wicket.validation.ValidationError;import org.apache.wicket.version.undo.Change;/** * An HTML form component knows how to validate itself. Validators that implement IValidator can be * added to the component. They will be evaluated in the order they were added and the first * Validator that returns an error message determines the error message returned by the component. * <p> * FormComponents are not versioned by default. If you need versioning for your FormComponents, you * will need to call Form.setVersioned(true), which will set versioning on for the form and all form * component children. * <p> * If this component is required and that fails, the error key that is used is the "Required"; if * the type conversion fails, it will use the key "IConverter". The keys that can be used in both * are: * <ul> * <li>${input}: the input the user did give</li> * <li>${name}: the name of the component that failed</li> * <li>${label}: the label of the component</li> * </ul> * * @author Jonathan Locke * @author Eelco Hillenius * @author Johan Compagner * @author Igor Vaynberg (ivaynberg) */public abstract class FormComponent extends LabeledWebMarkupContainer implements IFormVisitorParticipant{ /** * Visitor for traversing form components */ public static abstract class AbstractVisitor implements IVisitor { /** * @see org.apache.wicket.markup.html.form.FormComponent.IVisitor#formComponent(IFormVisitorParticipant) */ public Object formComponent(IFormVisitorParticipant component) { if (component instanceof FormComponent) { onFormComponent((FormComponent)component); } return Component.IVisitor.CONTINUE_TRAVERSAL; } protected abstract void onFormComponent(FormComponent formComponent); } /** * Typesafe interface to code that is called when visiting a form component. */ public static interface IVisitor { /** * Called when visiting a form component * * @param formComponent * The form component * @return component */ public Object formComponent(IFormVisitorParticipant formComponent); } /** * {@link IErrorMessageSource} used for error messages against this form components. * * @author ivaynberg */ private class MessageSource implements IErrorMessageSource { /** * @see org.apache.wicket.validation.IErrorMessageSource#getMessage(java.lang.String) */ public String getMessage(String key) { final FormComponent formComponent = FormComponent.this; // retrieve prefix that will be used to construct message keys String prefix = formComponent.getValidatorKeyPrefix(); if (Strings.isEmpty(prefix)) { prefix = ""; } final Localizer localizer = formComponent.getLocalizer(); String resource = prefix + getId() + "." + key; // First use the parent for resolving so that // form1.textfield1.Required can be used. // Note: It is important that the default value of "" is provided // to getString() not to throw a MissingResourceException or to // return a default string like "[Warning: String ..." String message = localizer.getString(resource, formComponent.getParent(), ""); // If not found, than ... if (Strings.isEmpty(message)) { // Try a variation of the resource key resource = prefix + key; message = localizer.getString(resource, formComponent.getParent(), ""); } if (Strings.isEmpty(message)) { // If still empty then use default resource = prefix + getId() + "." + key; // Note: It is important that the default value of "" is // provided // to getString() not to throw a MissingResourceException or to // return a default string like "[Warning: String ..." message = localizer.getString(resource, formComponent, ""); // If not found, than ... if (Strings.isEmpty(message)) { // Try a variation of the resource key resource = prefix + key; message = localizer.getString(resource, formComponent, ""); } } // convert empty string to null in case our default value of "" was // returned from localizer if (Strings.isEmpty(message)) { message = null; } return message; } /** * @see org.apache.wicket.validation.IErrorMessageSource#substitute(java.lang.String, * java.util.Map) */ public String substitute(String string, Map vars) throws IllegalStateException { return new MapVariableInterpolator(string, addDefaultVars(vars), Application.get() .getResourceSettings() .getThrowExceptionOnMissingResource()).toString(); } /** * Creates a new params map that additionally contains the default input, name, label * parameters * * @param params * original params map * @return new params map */ private Map addDefaultVars(Map params) { // create and fill the new params map final HashMap fullParams; if (params == null) { fullParams = new HashMap(6); } else { fullParams = new HashMap(params.size() + 6); fullParams.putAll(params); } // add the input param if not already present if (!fullParams.containsKey("input")) { fullParams.put("input", getInput()); } // add the name param if not already present if (!fullParams.containsKey("name")) { fullParams.put("name", getId()); } // add the label param if not already present if (!fullParams.containsKey("label")) { fullParams.put("label", getLabel()); } return fullParams; } /** * @return value of label param for this form component */ private Object getLabel() { final FormComponent fc = FormComponent.this; Object label = null; // first try the label model ... if (fc.getLabel() != null) { label = fc.getLabel().getObject(); } // ... then try a resource of format [form-component-id] with // default of '[form-component-id]' if (label == null) { label = fc.getLocalizer().getString(fc.getId(), fc.getParent(), fc.getId()); } return label; } } /** * Change object to capture the required flag change * * @author Igor Vaynberg (ivaynberg) */ private final class RequiredStateChange extends Change { private static final long serialVersionUID = 1L; private final boolean required = isRequired(); /** * @see org.apache.wicket.version.undo.Change#undo() */ public void undo() { setRequired(required); } } /** * Adapter that makes this component appear as {@link IValidatable} * * @author ivaynberg */ private class ValidatableAdapter implements IValidatable { /** * @see org.apache.wicket.validation.IValidatable#error(org.apache.wicket.validation.IValidationError) */ public void error(IValidationError error) { FormComponent.this.error(error); } /** * @see org.apache.wicket.validation.IValidatable#getValue() */ public Object getValue() { return getConvertedInput(); } public boolean isValid() { return FormComponent.this.isValid(); } } /** * The value separator */ public static String VALUE_SEPARATOR = ";"; private static final String[] EMPTY_STRING_ARRAY = new String[] { "" }; /** * Whether this form component should save and restore state between sessions. This is false by * default. */ private static final short FLAG_PERSISTENT = FLAG_RESERVED2; /** Whether or not this component's value is required (non-empty) */ private static final short FLAG_REQUIRED = FLAG_RESERVED3; private static final String NO_RAW_INPUT = "[-NO-RAW-INPUT-]"; private static final long serialVersionUID = 1L; /** * Make empty strings null values boolean. Used by AbstractTextComponent subclass. */ protected static final short FLAG_CONVERT_EMPTY_INPUT_STRING_TO_NULL = FLAG_RESERVED1; /** * Visits any form components inside component if it is a container, or component itself if it * is itself a form component * * @param component * starting point of the traversal * * @param visitor * The visitor to call */ public static final void visitFormComponentsPostOrder(Component component, final FormComponent.IVisitor visitor) { if (visitor == null) { throw new IllegalArgumentException("Argument `visitor` cannot be null"); } visitFormComponentsPostOrderHelper(component, visitor); } private static final Object visitFormComponentsPostOrderHelper(Component component, final FormComponent.IVisitor visitor) { if (component instanceof MarkupContainer) { final MarkupContainer container = (MarkupContainer)component; if (container.size() > 0) { boolean visitChildren = true; if (container instanceof IFormVisitorParticipant) { visitChildren = ((IFormVisitorParticipant)container).processChildren(); } if (visitChildren) { final Iterator children = container.iterator(); while (children.hasNext()) { final Component child = (Component)children.next(); Object value = visitFormComponentsPostOrderHelper(child, visitor); if (value == Component.IVisitor.STOP_TRAVERSAL) { return value; } } } } } if (component instanceof FormComponent) { final FormComponent fc = (FormComponent)component; return visitor.formComponent(fc); } return null; } private transient Object convertedInput; /** * Raw Input entered by the user or NO_RAW_INPUT if nothing is filled in. */ private String rawInput = NO_RAW_INPUT; /** * Type that the raw input string will be converted to */ private String typeName; /** * The list of validators for this form component as either an IValidator instance or an array * of IValidator instances. */ private Object validators = null; /** * @see org.apache.wicket.Component#Component(String) */ public FormComponent(final String id) { super(id); // the form decides whether form components are versioned or not // see Form.setVersioned setVersioned(false); } /** * @see org.apache.wicket.Component#Component(String, IModel) */ public FormComponent(final String id, IModel model) { super(id, model); // the form decides whether form components are versioned or not // see Form.setVersioned setVersioned(false); } /** * Adds a validator to this form component. * * @param validator * The validator * @return This * @throws IllegalArgumentException * if validator is null * @see IValidator * @see IValidatorAddListener */ public final FormComponent add(final IValidator validator) { if (validator == null) { throw new IllegalArgumentException("validator argument cannot be null"); } // add the validator validators_add(validator); // see whether the validator listens for add events if (validator instanceof IValidatorAddListener) { ((IValidatorAddListener)validator).onAdded(this); } // return this for chaining return this; } /**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -