001 // Copyright 2006, 2007, 2008, 2009 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
015 package org.apache.tapestry5.corelib.internal;
016
017 import org.apache.tapestry5.ComponentAction;
018 import org.apache.tapestry5.ComponentResources;
019 import org.apache.tapestry5.Field;
020 import org.apache.tapestry5.ioc.Locatable;
021 import org.apache.tapestry5.ioc.Location;
022 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
023 import org.apache.tapestry5.ioc.internal.util.Defense;
024 import org.apache.tapestry5.ioc.internal.util.IdAllocator;
025 import org.apache.tapestry5.services.ClientBehaviorSupport;
026
027 import java.util.List;
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 */
035 public 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,
068 boolean clientValidationEnabled, IdAllocator idAllocator, 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 if (commands == null) commands = CollectionFactory.newList();
109
110 commands.add(Defense.notNull(command, "command"));
111 }
112
113 public void executeDeferred()
114 {
115 if (commands == null) return;
116
117 for (Runnable r : commands)
118 r.run();
119
120 commands.clear();
121 }
122
123 public String getClientId()
124 {
125 return clientId;
126 }
127
128 public String getEncodingType()
129 {
130 return encodingType;
131 }
132
133 public void setEncodingType(String encodingType)
134 {
135 Defense.notBlank(encodingType, "encodingType");
136
137 if (this.encodingType != null && !this.encodingType.equals(encodingType))
138 throw new IllegalStateException(InternalMessages.conflictingEncodingType(this.encodingType, encodingType));
139
140 this.encodingType = encodingType;
141 }
142
143 public void addValidation(Field field, String validationName, String message, Object constraint)
144 {
145 if (clientValidationEnabled)
146 clientBehaviorSupport.addValidation(field, validationName, message, constraint);
147 }
148
149 public boolean isClientValidationEnabled()
150 {
151 return clientValidationEnabled;
152 }
153
154 public String getFormValidationId()
155 {
156 return formValidationId;
157 }
158 }