001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.validation;
018
019import java.util.ArrayList;
020import java.util.Collections;
021import java.util.Iterator;
022import java.util.List;
023
024import org.apache.wicket.Component;
025import org.apache.wicket.behavior.Behavior;
026import org.apache.wicket.event.IEvent;
027import org.apache.wicket.markup.ComponentTag;
028import org.apache.wicket.markup.head.IHeaderResponse;
029import org.apache.wicket.util.lang.Args;
030
031/**
032 * A compound {@link IValidator}. Once an error is reported against the {@link IValidatable} being
033 * checked, the rest of the validator chain is ignored.
034 * 
035 * @author Igor Vaynberg (ivaynberg)
036 * @param <T>
037 *            type of validatable
038 * @since 1.2.6
039 */
040public class CompoundValidator<T> extends Behavior implements IValidator<T>
041{
042        private static final long serialVersionUID = 1L;
043
044        private final List<IValidator<T>> validators = new ArrayList<IValidator<T>>(2);
045
046        /**
047         * Constructor.
048         */
049        public CompoundValidator()
050        {
051        }
052
053        /**
054         * Adds an <code>IValidator</code> to the chain of validators.
055         * 
056         * @param validator
057         *            an <code>IValidator</code> to be added
058         * @return this <code>ValidationError</code> for chaining purposes
059         */
060        public final CompoundValidator<T> add(IValidator<T> validator)
061        {
062                Args.notNull(validator, "validator");
063
064                validators.add(validator);
065                return this;
066        }
067
068        /**
069         * @see IValidator#validate(IValidatable)
070         */
071        @Override
072        public final void validate(IValidatable<T> validatable)
073        {
074                Iterator<IValidator<T>> it = validators.iterator();
075                while (it.hasNext() && validatable.isValid())
076                {
077                        it.next().validate(validatable);
078                }
079        }
080
081        /**
082         * Gets an unmodifiable list of the registered validators.
083         * 
084         * @return unmodifiable list of delegate {@link IValidator}s inside this one
085         */
086        public final List<IValidator<T>> getValidators()
087        {
088                return Collections.unmodifiableList(validators);
089        }
090
091        @Override
092        public void beforeRender(Component component)
093        {
094                for (IValidator<T> validator : validators) {
095                        if (validator instanceof Behavior) {
096                                ((Behavior)validator).beforeRender(component);
097                        }
098                }
099        }
100
101        @Override
102        public void afterRender(Component component)
103        {
104                for (IValidator<T> validator : validators) {
105                        if (validator instanceof Behavior) {
106                                ((Behavior)validator).afterRender(component);
107                        }
108                }
109        }
110
111        @Override
112        public void bind(Component component)
113        {
114                for (IValidator<T> validator : validators) {
115                        if (validator instanceof Behavior) {
116                                ((Behavior)validator).bind(component);
117                        }
118                }
119        }
120
121        @Override
122        public void unbind(Component component)
123        {
124                for (IValidator<T> validator : validators) {
125                        if (validator instanceof Behavior) {
126                                ((Behavior)validator).unbind(component);
127                        }
128                }
129        }
130        
131        @Override
132        public void detach(Component component)
133        {
134                for (IValidator<T> validator : validators) {
135                        if (validator instanceof Behavior) {
136                                ((Behavior)validator).detach(component);
137                        }
138                }
139        }
140
141        @Override
142        public void onException(Component component, RuntimeException exception)
143        {
144                for (IValidator<T> validator : validators) {
145                        if (validator instanceof Behavior) {
146                                ((Behavior)validator).onException(component, exception);
147                        }
148                }
149        }
150
151        @Override
152        public boolean getStatelessHint(Component component)
153        {
154                for (IValidator<T> validator : validators) {
155                        if (validator instanceof Behavior && ((Behavior)validator).getStatelessHint(component) == false) {
156                                return false;
157                        }
158                }
159                return super.getStatelessHint(component);
160        }
161
162        @Override
163        public void onComponentTag(Component component, ComponentTag tag)
164        {
165                for (IValidator<T> validator : validators) {
166                        if (validator instanceof Behavior) {
167                                ((Behavior)validator).onComponentTag(component, tag);
168                        }
169                }
170        }
171
172        @Override
173        public void renderHead(Component component, IHeaderResponse response)
174        {
175                for (IValidator<T> validator : validators) {
176                        if (validator instanceof Behavior) {
177                                ((Behavior)validator).renderHead(component, response);
178                        }
179                }
180        }
181
182        @Override
183        public void onConfigure(Component component)
184        {
185                for (IValidator<T> validator : validators) {
186                        if (validator instanceof Behavior) {
187                                ((Behavior)validator).onConfigure(component);
188                        }
189                }
190        }
191
192        @Override
193        public void onEvent(Component component, IEvent<?> event)
194        {
195                for (IValidator<T> validator : validators) {
196                        if (validator instanceof Behavior) {
197                                ((Behavior)validator).onEvent(component, event);
198                        }
199                }
200        }
201
202        @Override
203        public void onRemove(Component component)
204        {
205                for (IValidator<T> validator : validators) {
206                        if (validator instanceof Behavior) {
207                                ((Behavior)validator).onRemove(component);
208                        }
209                }
210        }
211}