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