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