001// Copyright 2006, 2007, 2008, 2009, 2010 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 java.util.List;
018
019import org.apache.tapestry5.ComponentAction;
020import org.apache.tapestry5.ComponentResources;
021import org.apache.tapestry5.Field;
022import org.apache.tapestry5.ioc.Locatable;
023import org.apache.tapestry5.ioc.Location;
024import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
025import org.apache.tapestry5.ioc.internal.util.InternalUtils;
026import org.apache.tapestry5.ioc.util.IdAllocator;
027import org.apache.tapestry5.services.ClientBehaviorSupport;
028
029/**
030 * Provides support to components enclosed by a form when the form is rendering (allowing the components to registry
031 * form submit callback commands), and also during form submission time.
032 * <p/>
033 * TODO: Most methods should only be invokable depending on whether the form is rendering or processing a submission.
034 */
035public class FormSupportImpl implements InternalFormSupport, Locatable
036{
037    private final ComponentResources resources;
038
039    private final ClientBehaviorSupport clientBehaviorSupport;
040
041    private final boolean clientValidationEnabled;
042
043    private final IdAllocator idAllocator;
044
045    private final String clientId;
046
047    private final ComponentActionSink actionSink;
048
049    private final String formValidationId;
050
051    private List<Runnable> commands;
052
053    private String encodingType;
054
055    /**
056     * Constructor used when processing a form submission.
057     */
058    public FormSupportImpl(ComponentResources resources, String formValidationId)
059    {
060        this(resources, null, null, null, false, null, formValidationId);
061    }
062
063    /**
064     * Full constructor (specifically constructor for render time).
065     */
066    public FormSupportImpl(ComponentResources resources, String clientId, ComponentActionSink actionSink,
067            ClientBehaviorSupport clientBehaviorSupport, boolean clientValidationEnabled, IdAllocator idAllocator,
068            String formValidationId)
069    {
070        this.resources = resources;
071        this.clientId = clientId;
072        this.actionSink = actionSink;
073        this.clientBehaviorSupport = clientBehaviorSupport;
074        this.clientValidationEnabled = clientValidationEnabled;
075        this.idAllocator = idAllocator;
076        this.formValidationId = formValidationId;
077    }
078
079    public Location getLocation()
080    {
081        return resources.getLocation();
082    }
083
084    public String getFormComponentId()
085    {
086        return resources.getCompleteId();
087    }
088
089    public String allocateControlName(String id)
090    {
091        return idAllocator.allocateId(id);
092    }
093
094    public <T> void store(T component, ComponentAction<T> action)
095    {
096        actionSink.store(component, action);
097    }
098
099    public <T> void storeAndExecute(T component, ComponentAction<T> action)
100    {
101        actionSink.store(component, action);
102
103        action.execute(component);
104    }
105
106    public void defer(Runnable command)
107    {
108        assert command != null;
109
110        if (commands == null)
111            commands = CollectionFactory.newList();
112
113        commands.add(command);
114    }
115
116    public void executeDeferred()
117    {
118        if (commands == null)
119            return;
120
121        for (Runnable r : commands)
122            r.run();
123
124        commands.clear();
125    }
126
127    public String getClientId()
128    {
129        return clientId;
130    }
131
132    public String getEncodingType()
133    {
134        return encodingType;
135    }
136
137    public void setEncodingType(String encodingType)
138    {
139        assert InternalUtils.isNonBlank(encodingType);
140
141        if (this.encodingType != null && !this.encodingType.equals(encodingType))
142            throw new IllegalStateException(InternalMessages.conflictingEncodingType(this.encodingType, encodingType));
143
144        this.encodingType = encodingType;
145    }
146
147    public void addValidation(Field field, String validationName, String message, Object constraint)
148    {
149        if (clientValidationEnabled)
150            clientBehaviorSupport.addValidation(field, validationName, message, constraint);
151    }
152
153    public boolean isClientValidationEnabled()
154    {
155        return clientValidationEnabled;
156    }
157
158    public String getFormValidationId()
159    {
160        return formValidationId;
161    }
162}