001 // Copyright 2004, 2005 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.tapestry.components;
016
017 import org.apache.hivemind.ApplicationRuntimeException;
018 import org.apache.hivemind.HiveMind;
019 import org.apache.tapestry.IActionListener;
020 import org.apache.tapestry.IBinding;
021 import org.apache.tapestry.IForm;
022 import org.apache.tapestry.IMarkupWriter;
023 import org.apache.tapestry.IRequestCycle;
024 import org.apache.tapestry.Tapestry;
025 import org.apache.tapestry.TapestryUtils;
026 import org.apache.tapestry.engine.NullWriter;
027 import org.apache.tapestry.form.AbstractFormComponent;
028 import org.apache.tapestry.services.DataSqueezer;
029
030 /**
031 * @author mb
032 */
033 public abstract class IfBean extends AbstractFormComponent
034 {
035 public static final String IF_VALUE_ATTRIBUTE = "org.mb.tapestry.base.IfValue";
036
037 private boolean _rendering = false;
038
039 private boolean _conditionValue;
040
041 public abstract IBinding getConditionValueBinding();
042
043 public abstract boolean getCondition();
044
045 public abstract boolean getVolatile();
046
047 public abstract String getElement();
048
049 public abstract IActionListener getListener();
050
051 protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
052 {
053 boolean cycleRewinding = cycle.isRewinding();
054
055 // form may be null if component is not located in a form
056 IForm form = (IForm) cycle.getAttribute(TapestryUtils.FORM_ATTRIBUTE);
057
058 // If the cycle is rewinding, but not this particular form,
059 // then do nothing (don't even render the body).
060 if (cycleRewinding && form != null && !form.isRewinding())
061 return;
062
063 // get the condition. work with a hidden field if necessary
064 _conditionValue = evaluateCondition(cycle, form, cycleRewinding);
065 _rendering = true;
066
067 if (!cycleRewinding && form != null && !NullWriter.class.isInstance(writer))
068 form.setFormFieldUpdating(true);
069
070 try
071 {
072 // call listener
073 IActionListener listener = getListener();
074 if (listener != null)
075 listener.actionTriggered(this, cycle);
076
077 // now render if condition is true
078 if (_conditionValue)
079 {
080 String element = getElement();
081
082 boolean render = !cycleRewinding && HiveMind.isNonBlank(element);
083
084 if (render)
085 {
086 writer.begin(element);
087 renderInformalParameters(writer, cycle);
088 }
089
090 renderBody(writer, cycle);
091
092 if (render)
093 writer.end(element);
094 }
095 }
096 finally
097 {
098 _rendering = false;
099 }
100
101 cycle.setAttribute(IF_VALUE_ATTRIBUTE, new Boolean(_conditionValue));
102 }
103
104 protected boolean evaluateCondition(IRequestCycle cycle, IForm form, boolean cycleRewinding)
105 {
106 boolean condition;
107
108 if (form == null || getVolatile())
109 {
110 condition = getCondition();
111 }
112 else
113 {
114 // we are in a form and we care -- load/store the condition in a hidden field
115 String name = form.getElementId(this);
116
117 if (!cycleRewinding)
118 {
119 condition = getCondition();
120 writeValue(form, name, condition);
121 }
122 else
123 {
124 condition = readValue(cycle, name);
125 }
126 }
127
128 // write condition value if parameter is bound
129 IBinding conditionValueBinding = getConditionValueBinding();
130 if (conditionValueBinding != null)
131 conditionValueBinding.setObject(new Boolean(condition));
132
133 return condition;
134 }
135
136 private void writeValue(IForm form, String name, boolean value)
137 {
138 String externalValue;
139
140 Object booleanValue = new Boolean(value);
141 try
142 {
143 externalValue = getDataSqueezer().squeeze(booleanValue);
144 }
145 catch (Exception ex)
146 {
147 throw new ApplicationRuntimeException(Tapestry.format(
148 "If.unable-to-convert-value",
149 booleanValue), this, null, ex);
150 }
151
152 form.addHiddenValue(name, externalValue);
153 }
154
155 private boolean readValue(IRequestCycle cycle, String name)
156 {
157 String submittedValue = cycle.getParameter(name);
158
159 try
160 {
161 Object valueObject = getDataSqueezer().unsqueeze(submittedValue);
162 if (!(valueObject instanceof Boolean))
163 throw new ApplicationRuntimeException(Tapestry.format(
164 "If.invalid-condition-type",
165 submittedValue));
166
167 return ((Boolean) valueObject).booleanValue();
168 }
169 catch (Exception ex)
170 {
171 throw new ApplicationRuntimeException(Tapestry.format(
172 "If.unable-to-convert-string",
173 submittedValue), this, null, ex);
174 }
175 }
176
177 public abstract DataSqueezer getDataSqueezer();
178
179 public boolean isDisabled()
180 {
181 return false;
182 }
183
184 /**
185 * Returns the value of the condition.
186 *
187 * @return the condition value
188 */
189 public boolean getConditionValue()
190 {
191 if (!_rendering)
192 throw Tapestry.createRenderOnlyPropertyException(this, "conditionValue");
193
194 return _conditionValue;
195 }
196
197 // Do nothing in those methods, but make the JVM happy
198 protected void renderFormComponent(IMarkupWriter writer, IRequestCycle cycle)
199 {
200 }
201
202 protected void rewindFormComponent(IMarkupWriter writer, IRequestCycle cycle)
203 {
204 }
205
206 /**
207 * For component can not take focus.
208 */
209 protected boolean getCanTakeFocus()
210 {
211 return false;
212 }
213 }