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.markup.html.form;
018
019import java.util.Iterator;
020import java.util.List;
021
022import org.apache.wicket.model.IModel;
023import org.apache.wicket.request.mapper.parameter.INamedParameters;
024import org.apache.wicket.request.mapper.parameter.PageParameters;
025import org.apache.wicket.util.string.Strings;
026import org.apache.wicket.util.visit.IVisit;
027import org.apache.wicket.util.visit.IVisitor;
028
029/**
030 * This StatelessForm is the same as a normal form but with the statelesshint default to true. The
031 * form can be newly constructed when the onSubmit of its form or its buttons is called. So you
032 * can't depend on state within the page. The only state you can depend on is what was submitted
033 * from the browser. So the model of the form or the formcomponents are updated with the submit
034 * values.
035 *
036 * <strong>Note</strong>: Use {@link org.apache.wicket.markup.repeater.RepeatingView} in the case when
037 * {@link org.apache.wicket.markup.html.form.FormComponent}s need to be rendered inside a repeater. See
038 * the javadoc of {@link org.apache.wicket.markup.repeater.AbstractRepeater} for more information.
039 *
040 * @author jcompagner
041 * @param <T>
042 *            The type of the {@link Form}'s model object
043 */
044public class StatelessForm<T> extends Form<T>
045{
046        private static final long serialVersionUID = 1L;
047
048        /**
049         * Construct.
050         * 
051         * @param id
052         */
053        public StatelessForm(String id)
054        {
055                super(id);
056        }
057
058        /**
059         * Construct.
060         * 
061         * @param id
062         * @param model
063         */
064        public StatelessForm(String id, IModel<T> model)
065        {
066                super(id, model);
067        }
068
069        @Override
070        protected boolean getStatelessHint()
071        {
072                return true;
073        }
074
075        @Override
076        protected MethodMismatchResponse onMethodMismatch()
077        {
078                setResponsePage(getPage().getClass(), getPage().getPageParameters());
079                return MethodMismatchResponse.ABORT;
080        }
081
082        @Override
083        protected CharSequence getActionUrl()
084        {
085                return urlForListener(getPage().getPageParameters());
086        }
087
088        /**
089         * Remove the page parameters for all form component otherwise they get appended to action URL
090         *
091         * {@inheritDoc}
092         */
093        @Override
094        public void process(IFormSubmitter submittingComponent)
095        {
096                // get the parameters before processing the form because the
097                // application may remove this form from its parent in #onSubmit() (WICKET-5158)
098                final PageParameters parameters = getPage().getPageParameters();
099
100                super.process(submittingComponent);
101
102                if (parameters != null)
103                {
104                        visitFormComponents(new IVisitor<FormComponent<?>, Void>()
105                        {
106                                @Override
107                                public void component(final FormComponent<?> formComponent, final IVisit<Void> visit)
108                                {
109                                        parameters.remove(formComponent.getInputName());
110                                }
111                        });
112                        if (submittingComponent instanceof AbstractSubmitLink)
113                        {
114                                AbstractSubmitLink submitLink = (AbstractSubmitLink)submittingComponent;
115                                parameters.remove(submitLink.getInputName());
116                        }
117
118                        // remove the special parameter for IRequestListener
119                        List<INamedParameters.NamedPair> namedParameters = parameters.getAllNamed();
120                        Iterator<INamedParameters.NamedPair> iterator = namedParameters.iterator();
121                        while (iterator.hasNext())
122                        {
123                                INamedParameters.NamedPair namedParameter = iterator.next();
124                                if (Strings.isEmpty(namedParameter.getValue()))
125                                {
126                                        parameters.remove(namedParameter.getKey());
127                                        break;
128                                }
129                        }
130                }
131        }
132}