001// Licensed under the Apache License, Version 2.0 (the "License");
002// you may not use this file except in compliance with the License.
003// You may obtain a copy of the License at
004//
005// http://www.apache.org/licenses/LICENSE-2.0
006//
007// Unless required by applicable law or agreed to in writing, software
008// distributed under the License is distributed on an "AS IS" BASIS,
009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
010// See the License for the specific language governing permissions and
011// limitations under the License.
012
013package org.apache.tapestry5.corelib.internal;
014
015import org.apache.tapestry5.ComponentAction;
016import org.apache.tapestry5.ComponentResources;
017import org.apache.tapestry5.Field;
018import org.apache.tapestry5.commons.Locatable;
019import org.apache.tapestry5.commons.Location;
020import org.apache.tapestry5.commons.util.CollectionFactory;
021import org.apache.tapestry5.ioc.internal.util.InternalUtils;
022import org.apache.tapestry5.ioc.util.IdAllocator;
023
024import java.util.List;
025
026/**
027 * Provides support to components enclosed by a form when the form is rendering (allowing the components to registry
028 * form submit callback commands), and also during form submission time.
029 *
030 * TODO: Most methods should only be invokable depending on whether the form is rendering or processing a submission.
031 */
032public class FormSupportImpl implements InternalFormSupport, Locatable
033{
034    private final ComponentResources resources;
035
036    private final boolean clientValidationEnabled;
037
038    private final IdAllocator idAllocator;
039
040    private final String clientId;
041
042    private final ComponentActionSink actionSink;
043
044    private final String formValidationId;
045
046    private List<Runnable> commands;
047
048    private String encodingType;
049
050    /**
051     * Constructor used when processing a form submission.
052     */
053    public FormSupportImpl(ComponentResources resources, String formValidationId)
054    {
055        this(resources, null, null, false, null, formValidationId);
056    }
057
058    /**
059     * Full constructor (specifically constructor for render time).
060     */
061    public FormSupportImpl(ComponentResources resources, String clientId, ComponentActionSink actionSink,
062                           boolean clientValidationEnabled, IdAllocator idAllocator,
063                           String formValidationId)
064    {
065        this.resources = resources;
066        this.clientId = clientId;
067        this.actionSink = actionSink;
068        this.clientValidationEnabled = clientValidationEnabled;
069        this.idAllocator = idAllocator;
070        this.formValidationId = formValidationId;
071    }
072
073    public Location getLocation()
074    {
075        return resources.getLocation();
076    }
077
078    public String getFormComponentId()
079    {
080        return resources.getCompleteId();
081    }
082
083    public String allocateControlName(String id)
084    {
085        return idAllocator.allocateId(id);
086    }
087
088    public <T> void store(T component, ComponentAction<T> action)
089    {
090        actionSink.store(component, action);
091    }
092
093    public <T> void storeCancel(T component, ComponentAction<T> action)
094    {
095        actionSink.storeCancel(component, action);
096    }
097
098    public <T> void storeAndExecute(T component, ComponentAction<T> action)
099    {
100        actionSink.store(component, action);
101
102        action.execute(component);
103    }
104
105    public void defer(Runnable command)
106    {
107        assert command != null;
108
109        if (commands == null)
110            commands = CollectionFactory.newList();
111
112        commands.add(command);
113    }
114
115    public void executeDeferred()
116    {
117        if (commands == null)
118            return;
119
120        for (Runnable r : commands)
121            r.run();
122
123        commands.clear();
124    }
125
126    public String getClientId()
127    {
128        return clientId;
129    }
130
131    public String getEncodingType()
132    {
133        return encodingType;
134    }
135
136    public void setEncodingType(String encodingType)
137    {
138        assert InternalUtils.isNonBlank(encodingType);
139
140        if (this.encodingType != null && !this.encodingType.equals(encodingType))
141            throw new IllegalStateException(String.format("Encoding type of form has already been set to '%s' and may not be changed to '%s'.", this.encodingType, encodingType));
142
143        this.encodingType = encodingType;
144    }
145
146    public void addValidation(Field field, String validationName, String message, Object constraint)
147    {
148    }
149
150    public boolean isClientValidationEnabled()
151    {
152        return clientValidationEnabled;
153    }
154
155    public String getFormValidationId()
156    {
157        return formValidationId;
158    }
159}