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.contrib.form;
016
017 import org.apache.hivemind.ApplicationRuntimeException;
018 import org.apache.hivemind.HiveMind;
019 import org.apache.tapestry.AbstractComponent;
020 import org.apache.tapestry.IActionListener;
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.form.IFormComponent;
027 import org.apache.tapestry.listener.ListenerInvoker;
028 import org.apache.tapestry.services.DataSqueezer;
029
030 /**
031 * A conditional element on a page which will render its wrapped elements zero
032 * or one times. This component is a variant of
033 * {@link org.apache.tapestry.components.Conditional}, but is designed for
034 * operation in a form. The component parameters are stored in hidden fields
035 * during rendering and are taken from those fields during the rewind, thus no
036 * StaleLink exceptions occur. [ <a
037 * href="../../../../../ComponentReference/contrib.FormConditional.html">Component
038 * Reference </a>]
039 *
040 * @author Mindbridge
041 * @since 3.0
042 */
043
044 public abstract class FormConditional extends AbstractComponent implements
045 IFormComponent
046 {
047
048 protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
049 {
050 IForm form = TapestryUtils.getForm(cycle, this);
051
052 boolean cycleRewinding = cycle.isRewinding();
053
054 // If the cycle is rewinding, but not this particular form,
055 // then do nothing (don't even render the body).
056
057 if (cycleRewinding && !form.isRewinding()) return;
058
059 String name = form.getElementId(this);
060
061 boolean condition = getCondition(cycle, form, name);
062
063 getListenerInvoker().invokeListener(getListener(), this, cycle);
064
065 // render the component body only if the condition is true
066 if (condition)
067 {
068 String element = getElement();
069
070 boolean render = !cycleRewinding && HiveMind.isNonBlank(element);
071
072 if (render)
073 {
074 writer.begin(element);
075 renderInformalParameters(writer, cycle);
076 }
077
078 renderBody(writer, cycle);
079
080 if (render) writer.end(element);
081 }
082 }
083
084 private boolean getCondition(IRequestCycle cycle, IForm form, String name)
085 {
086 boolean condition;
087
088 if (!cycle.isRewinding())
089 {
090 condition = getCondition();
091 writeValue(form, name, condition);
092 }
093 else
094 {
095 String submittedCondition = cycle.getParameter(name);
096 condition = convertValue(submittedCondition);
097 }
098
099 if (isParameterBound("conditionValue")) setConditionValue(condition);
100
101 return condition;
102 }
103
104 private void writeValue(IForm form, String name, boolean value)
105 {
106 String externalValue;
107
108 try
109 {
110 externalValue = getDataSqueezer().squeeze(
111 value ? Boolean.TRUE : Boolean.FALSE);
112 }
113 catch (Exception ex)
114 {
115 throw new ApplicationRuntimeException(Tapestry.format(
116 "FormConditional.unable-to-convert-value", Boolean
117 .toString(value)), this, null, ex);
118 }
119
120 form.addHiddenValue(name, externalValue);
121 }
122
123 private boolean convertValue(String value)
124 {
125 try
126 {
127 Boolean b = (Boolean) getDataSqueezer().unsqueeze(value);
128 return b.booleanValue();
129 }
130 catch (Exception ex)
131 {
132 throw new ApplicationRuntimeException(Tapestry.format(
133 "FormConditional.unable-to-convert-string", value), this,
134 null, ex);
135 }
136 }
137
138 public abstract DataSqueezer getDataSqueezer();
139
140 // Part of the FormElement interface.
141
142 public boolean isDisabled()
143 {
144 return false;
145 }
146
147 public abstract boolean getCondition();
148
149 public abstract void setConditionValue(boolean value);
150
151 public abstract String getElement();
152
153 public abstract IActionListener getListener();
154
155 /**
156 * Injected.
157 *
158 * @since 4.0
159 */
160
161 public abstract ListenerInvoker getListenerInvoker();
162
163 }