<commit_before>/*
 * $Id$
 * $Revision$
 * $Date$
 *
 * ====================================================================
 * Licensed 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 wicket.markup.html.form;

import java.io.Serializable;

import wicket.markup.ComponentTag;
import wicket.markup.html.HtmlContainer;
import wicket.markup.html.form.validation.IValidator;
import wicket.markup.html.form.validation.ValidationErrorMessage;
import wicket.model.IModel;
import wicket.util.lang.Classes;
import wicket.util.string.StringList;

/**
 * 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.
 *
 * @author <NAME>
 * @author <NAME>
 */
public abstract class FormComponent extends HtmlContainer
{
    /** The validator or validator list for this component. */
    private IValidator validator = IValidator.NULL;

    /**
     * Whether this form component should save and restore state from cookies.
     * This is false by default.
     */
    private boolean persistenceEnabled = false;
    
    // TODO add boolean "invalid" and override model getter to use request when form component is invalid

    /**
     * Constructor.
     * @param componentName The name of this component
     */
    public FormComponent(final String componentName)
    {
        super(componentName);
    }

    /**
     * Constructor that uses the provided {@link IModel} as its model. All components have
     * names. A component's name cannot be null.
     * @param name The non-null name of this component
     * @param model the model
     * @throws wicket.WicketRuntimeException Thrown if the component
     * has been given a null name.
     */
    public FormComponent(String name, IModel model)
    {
        super(name, model);
    }

    /**
     * Constructor that uses the provided instance of {@link IModel} as a dynamic model.
     * This model will be wrapped in an instance of {@link wicket.model.PropertyModel}
     * using the provided expression. Thus, using this constructor is a short-hand for:
     * 
     * <pre>
     * new MyComponent(name, new PropertyModel(myIModel, expression));
     * </pre>
     * 
     * All components have names. A component's name cannot be null.
     * @param name The non-null name of this component
     * @param model the instance of {@link IModel} from which the model object will be
     *            used as the subject for the given expression
     * @param expression the OGNL expression that works on the given object
     * @throws wicket.WicketRuntimeException Thrown if the component has
     * been given a null name.
     */
    public FormComponent(String name, IModel model, String expression)
    {
        super(name, model, expression);
    }

    /**
     * Constructor that uses the provided object as a simple model. This object will be
     * wrapped in an instance of {@link wicket.model.Model}. All components
     * have names. A component's name cannot be null.
     * @param name The non-null name of this component
     * @param object the object that will be used as a simple model
     * @throws wicket.WicketRuntimeException Thrown if the component has
     * been given a null name.
     */
    public FormComponent(String name, Serializable object)
    {
        super(name, object);
    }

    /**
     * Constructor that uses the provided object as a dynamic model. This object will be
     * wrapped in an instance of {@link wicket.model.Model} that will be wrapped i
     * n an instance of {@link wicket.model.PropertyModel} using the provided
     * expression. Thus, using this constructor is a short-hand for:
     * 
     * <pre>
     * new MyComponent(name, new PropertyModel(new Model(object), expression));
     * </pre>
     * 
     * All components have names. A component's name cannot be null.
     * @param name The non-null name of this component
     * @param object the object that will be used as the subject for the given expression
     * @param expression the OGNL expression that works on the given object
     * @throws wicket.WicketRuntimeException Thrown if the component has
     * been given a null name.
     */
    public FormComponent(String name, Serializable object, String expression)
    {
        super(name, object, expression);
    }

    /**
     * Gets whether this component is to be persisted.
     * @return whether this component is to be persisted
     */
    public final boolean isPersistenceEnabled()
    {
        return persistenceEnabled;
    }

    /**
     * Sets whether this component is to be persisted.
     * @param persistenceEnabled whether this component is to be persisted.
     */
    public final void setPersistenceEnabled(final boolean persistenceEnabled)
    {
        if (this instanceof ICookieValue)
        {
            this.persistenceEnabled = persistenceEnabled;
        }
        else
        {
            throw new UnsupportedOperationException("FormComponent "
                    + getClass().getName() + " does not support cookies");
        }
    }

    /**
     * Implemented by form component subclass to update the form
     * component's model.
     */
    public abstract void updateModel();

    /**
     * Validates this component and returns an optional message. If a message
     * is returned, and its level is higher than ValidationErrorMessage.ERROR, the form
     * will be in error state. A message with a lower level than that however, will
     * be recorded, but will not have the form fail.
     * @return the {@link ValidationErrorMessage} or null (ValidationErrorMessage.NO_MESSAGE).
     */
    public final ValidationErrorMessage validate()
    {
        return validator.validate(this);
    }
    
    /**
	 * Processes the component tag.
	 * @param tag Tag to modify
     * @see wicket.Component#handleComponentTag(ComponentTag)
     */
    protected void handleComponentTag(final ComponentTag tag)
    {
        super.handleComponentTag(tag);
        tag.put("name", getPath());
    }

    /**
     * Adds a validator to this form component.
     * @param validator The validator
     * @return This
     */
    public final FormComponent add(final IValidator validator)
    {
        // If we don't yet have a validator
        if (this.validator == IValidator.NULL)
        {
            // Just add the validator directly
            this.validator = validator;
        }
        else
        {
            // Create a validator list?
            if (this.validator instanceof ValidatorList)
            {
                // Already have a list. Just add new validator to list
                ((ValidatorList)this.validator).add(validator);
            }
            else
            {
                // Create a set of the current validator and the new validator
                this.validator = new ValidatorList(this.validator, validator);
            }
        }

        return this;
    }

    /**
     * Gets whether this component is to be validated.
     * @return True if this component has one or more validators
     */
    public final boolean isValidated()
    {
        return this.validator != IValidator.NULL;
    }

    /**
     * Interface to components that support getting and setting cookie
     * values to allow for persistent state in the user's browser.
     */
    public interface ICookieValue
    {
        /**
         * Gets a cookie value for a form component.
         * @return The cookie value
         */
        public String getCookieValue();

        /**
         * Sets a cookie value for a form component.
         * @param value The cookie value
         */
        public void setCookieValue(final String value);
    }

    /**
     * A convenient and memory efficent representation for a list
     * of validators.
     */
    static private final class ValidatorList implements IValidator
    {
        /**
         * Left part of linked list.
         */
        private final IValidator left;

        /**
         * Right part of linked list.
         */
        private IValidator right;

        /**
         * Constructs a list with validators in it.
         * @param left The left validator
         * @param right The right validator
         */
        ValidatorList(final IValidator left, final IValidator right)
        {
            this.left = left;
            this.right = right;
        }

        /**
         * Adds the given code validator to this list of code validators.
         * @param validator The validator
         */
        void add(final IValidator validator)
        {
            ValidatorList current = this;

            while (current.right instanceof ValidatorList)
            {
                current = (ValidatorList)current.right;
            }

            current.right = new ValidatorList(current.right, validator);
        }

        /**
         * Validates the given component.
         * @param component The component to validate
         * @return The error returned by the first validator in the list which reported an
         *         error or null if no validator reported an error
         */
        public ValidationErrorMessage validate(final FormComponent component)
        {
            final ValidationErrorMessage message = left.validate(component);

            if (message != ValidationErrorMessage.NO_MESSAGE && message.isLevelError())
            {
                return message;
            }

            return right.validate(component);
        }

        /**
         * Gets the string representation of this object.
         * @return String representation of this object
         */
        public String toString()
        {
            final StringList stringList = new StringList();
            ValidatorList current = this;

            while (true)
            {
                stringList.add(Classes.name(current.left.getClass())
                        + " " + current.left.toString());

                if (current.right instanceof ValidatorList)
                {
                    current = (ValidatorList)current.right;
                }
                else
                {
                    stringList.add(Classes.name(current.right.getClass())
                            + " " + current.right.toString());

                    break;
                }
            }

            return stringList.toString();
        }
    }
}<commit_msg>added the ability to ask a form component what validators are registered with it.<commit_after>/*
 * $Id$
 * $Revision$
 * $Date$
 *
 * ====================================================================
 * Licensed 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 wicket.markup.html.form;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import wicket.markup.ComponentTag;
import wicket.markup.html.HtmlContainer;
import wicket.markup.html.form.validation.IValidator;
import wicket.markup.html.form.validation.ValidationErrorMessage;
import wicket.model.IModel;
import wicket.util.lang.Classes;
import wicket.util.string.StringList;

/**
 * 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.
 *
 * @author <NAME>
 * @author <NAME>
 */
public abstract class FormComponent extends HtmlContainer
{
    /** The validator or validator list for this component. */
    private IValidator validator = IValidator.NULL;

    /**
     * Whether this form component should save and restore state from cookies.
     * This is false by default.
     */
    private boolean persistenceEnabled = false;
    
    // TODO add boolean "invalid" and override model getter to use request when form component is invalid

    /**
     * Constructor.
     * @param componentName The name of this component
     */
    public FormComponent(final String componentName)
    {
        super(componentName);
    }

    /**
     * Constructor that uses the provided {@link IModel} as its model. All components have
     * names. A component's name cannot be null.
     * @param name The non-null name of this component
     * @param model the model
     * @throws wicket.WicketRuntimeException Thrown if the component
     * has been given a null name.
     */
    public FormComponent(String name, IModel model)
    {
        super(name, model);
    }

    /**
     * Constructor that uses the provided instance of {@link IModel} as a dynamic model.
     * This model will be wrapped in an instance of {@link wicket.model.PropertyModel}
     * using the provided expression. Thus, using this constructor is a short-hand for:
     * 
     * <pre>
     * new MyComponent(name, new PropertyModel(myIModel, expression));
     * </pre>
     * 
     * All components have names. A component's name cannot be null.
     * @param name The non-null name of this component
     * @param model the instance of {@link IModel} from which the model object will be
     *            used as the subject for the given expression
     * @param expression the OGNL expression that works on the given object
     * @throws wicket.WicketRuntimeException Thrown if the component has
     * been given a null name.
     */
    public FormComponent(String name, IModel model, String expression)
    {
        super(name, model, expression);
    }

    /**
     * Constructor that uses the provided object as a simple model. This object will be
     * wrapped in an instance of {@link wicket.model.Model}. All components
     * have names. A component's name cannot be null.
     * @param name The non-null name of this component
     * @param object the object that will be used as a simple model
     * @throws wicket.WicketRuntimeException Thrown if the component has
     * been given a null name.
     */
    public FormComponent(String name, Serializable object)
    {
        super(name, object);
    }

    /**
     * Constructor that uses the provided object as a dynamic model. This object will be
     * wrapped in an instance of {@link wicket.model.Model} that will be wrapped i
     * n an instance of {@link wicket.model.PropertyModel} using the provided
     * expression. Thus, using this constructor is a short-hand for:
     * 
     * <pre>
     * new MyComponent(name, new PropertyModel(new Model(object), expression));
     * </pre>
     * 
     * All components have names. A component's name cannot be null.
     * @param name The non-null name of this component
     * @param object the object that will be used as the subject for the given expression
     * @param expression the OGNL expression that works on the given object
     * @throws wicket.WicketRuntimeException Thrown if the component has
     * been given a null name.
     */
    public FormComponent(String name, Serializable object, String expression)
    {
        super(name, object, expression);
    }

    /**
     * Gets whether this component is to be persisted.
     * @return whether this component is to be persisted
     */
    public final boolean isPersistenceEnabled()
    {
        return persistenceEnabled;
    }

    /**
     * Sets whether this component is to be persisted.
     * @param persistenceEnabled whether this component is to be persisted.
     */
    public final void setPersistenceEnabled(final boolean persistenceEnabled)
    {
        if (this instanceof ICookieValue)
        {
            this.persistenceEnabled = persistenceEnabled;
        }
        else
        {
            throw new UnsupportedOperationException("FormComponent "
                    + getClass().getName() + " does not support cookies");
        }
    }

    /**
     * Implemented by form component subclass to update the form
     * component's model.
     */
    public abstract void updateModel();

    /**
     * Validates this component and returns an optional message. If a message
     * is returned, and its level is higher than ValidationErrorMessage.ERROR, the form
     * will be in error state. A message with a lower level than that however, will
     * be recorded, but will not have the form fail.
     * @return the {@link ValidationErrorMessage} or null (ValidationErrorMessage.NO_MESSAGE).
     */
    public final ValidationErrorMessage validate()
    {
        return validator.validate(this);
    }
    
    /**
	 * Processes the component tag.
	 * @param tag Tag to modify
     * @see wicket.Component#handleComponentTag(ComponentTag)
     */
    protected void handleComponentTag(final ComponentTag tag)
    {
        super.handleComponentTag(tag);
        tag.put("name", getPath());
    }

    /**
     * Adds a validator to this form component.
     * @param validator The validator
     * @return This
     */
    public final FormComponent add(final IValidator validator)
    {
        // If we don't yet have a validator
        if (this.validator == IValidator.NULL)
        {
            // Just add the validator directly
            this.validator = validator;
        }
        else
        {
            // Create a validator list?
            if (this.validator instanceof ValidatorList)
            {
                // Already have a list. Just add new validator to list
                ((ValidatorList)this.validator).add(validator);
            }
            else
            {
                // Create a set of the current validator and the new validator
                this.validator = new ValidatorList(this.validator, validator);
            }
        }

        return this;
    }

    /**
     * Gets the registered validators as a list.
    * @return the validators as a list
    */
   public final List getValidators()
    {
    	final List l;
    	if(this.validator == null)
    	{
    		l = Collections.EMPTY_LIST;
    	}
    	else if(this.validator instanceof ValidatorList)
    	{
    		l = ((ValidatorList)this.validator).asList();
    	}
    	else
    	{
    		l = new ArrayList(1);	
	    	l.add(validator);
    	}
    	return l;
    }

    /**
     * Gets whether this component is to be validated.
     * @return True if this component has one or more validators
     */
    public final boolean isValidated()
    {
        return this.validator != IValidator.NULL;
    }

    /**
     * Interface to components that support getting and setting cookie
     * values to allow for persistent state in the user's browser.
     */
    public interface ICookieValue
    {
        /**
         * Gets a cookie value for a form component.
         * @return The cookie value
         */
        public String getCookieValue();

        /**
         * Sets a cookie value for a form component.
         * @param value The cookie value
         */
        public void setCookieValue(final String value);
    }

    /**
     * A convenient and memory efficent representation for a list
     * of validators.
     */
    static private final class ValidatorList implements IValidator
    {
        /**
         * Left part of linked list.
         */
        private final IValidator left;

        /**
         * Right part of linked list.
         */
        private IValidator right;

        /**
         * Constructs a list with validators in it.
         * @param left The left validator
         * @param right The right validator
         */
        ValidatorList(final IValidator left, final IValidator right)
        {
            this.left = left;
            this.right = right;
        }

        /**
         * Adds the given code validator to this list of code validators.
         * @param validator The validator
         */
        void add(final IValidator validator)
        {
            ValidatorList current = this;

            while (current.right instanceof ValidatorList)
            {
                current = (ValidatorList)current.right;
            }

            current.right = new ValidatorList(current.right, validator);
        }

        /**
         * Gets the validators as a List.
         * @return the validators as a List
         */
        List asList()
        {
         ValidatorList current = this;
         List validators = new ArrayList();
         while (true)
         {
         	validators.add(current.left);
             if (current.right instanceof ValidatorList)
             {
                 current = (ValidatorList)current.right;
             }
             else
             {
             	validators.add(current.right);
                 break;
             }
         }
         return validators;
        }

        /**
         * Validates the given component.
         * @param component The component to validate
         * @return The error returned by the first validator in the list which reported an
         *         error or null if no validator reported an error
         */
        public ValidationErrorMessage validate(final FormComponent component)
        {
            final ValidationErrorMessage message = left.validate(component);

            if (message != ValidationErrorMessage.NO_MESSAGE && message.isLevelError())
            {
                return message;
            }

            return right.validate(component);
        }

        /**
         * Gets the string representation of this object.
         * @return String representation of this object
         */
        public String toString()
        {
            final StringList stringList = new StringList();
            ValidatorList current = this;

            while (true)
            {
                stringList.add(Classes.name(current.left.getClass())
                        + " " + current.left.toString());

                if (current.right instanceof ValidatorList)
                {
                    current = (ValidatorList)current.right;
                }
                else
                {
                    stringList.add(Classes.name(current.right.getClass())
                            + " " + current.right.toString());

                    break;
                }
            }

            return stringList.toString();
        }
    }
}
{'fraction_non_alphanumeric': 0.07903941306944208, 'fraction_numerical': 0.00038389353352670194, 'mean_word_length': 2.060305443153635, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5829274', 'n_tokens_mistral': 5817, 'n_tokens_neox': 5662, 'n_words': 2225}