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.commons.logging.Log; 018 import org.apache.commons.logging.LogFactory; 019 import org.apache.hivemind.ApplicationRuntimeException; 020 import org.apache.hivemind.HiveMind; 021 import org.apache.tapestry.*; 022 import org.apache.tapestry.engine.NullWriter; 023 import org.apache.tapestry.form.AbstractFormComponent; 024 import org.apache.tapestry.services.DataSqueezer; 025 026 /** 027 * @author mb 028 */ 029 public abstract class IfBean extends AbstractFormComponent 030 { 031 public static final Log _log = LogFactory.getLog(IfBean.class); 032 033 public static final String IF_VALUE_ATTRIBUTE = "org.mb.tapestry.base.IfValue"; 034 035 private boolean _rendering = false; 036 037 private boolean _conditionValue; 038 039 public abstract IBinding getConditionValueBinding(); 040 041 public abstract boolean getCondition(); 042 043 public abstract boolean getVolatile(); 044 045 public abstract String getElement(); 046 047 public abstract boolean getRenderTag(); 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 061 if (cycleRewinding && form != null && !form.isRewinding()) 062 return; 063 064 // get the condition. work with a hidden field if necessary 065 066 _conditionValue = evaluateCondition(cycle, form, cycleRewinding); 067 _rendering = true; 068 069 if (!cycleRewinding && form != null && !NullWriter.class.isInstance(writer)) 070 form.setFormFieldUpdating(true); 071 072 try 073 { 074 // call listener 075 IActionListener listener = getListener(); 076 if (listener != null) 077 listener.actionTriggered(this, cycle); 078 079 // now render if condition is true 080 if (_conditionValue) 081 { 082 String element = HiveMind.isNonBlank(getElement()) ? getElement() : getTemplateTagName(); 083 084 boolean render = !cycleRewinding && (getRenderTag() || HiveMind.isNonBlank(getElement())); 085 086 if (render) 087 { 088 writer.begin(element); 089 090 renderInformalParameters(writer, cycle); 091 renderIdAttribute(writer, cycle); 092 } 093 094 renderBody(writer, cycle); 095 096 if (render) 097 writer.end(element); 098 } 099 } 100 finally 101 { 102 _rendering = false; 103 } 104 105 cycle.setAttribute(IF_VALUE_ATTRIBUTE, new Boolean(_conditionValue)); 106 } 107 108 /** 109 * Overriden from {@link AbstractFormComponent} to handle cases where 110 * we're not being wrapped by a {@link IForm} component. 111 * 112 * <p>This is basically a copy of the same method implemented in {@link AbstractComponent}.</p> 113 */ 114 protected void generateClientId() 115 { 116 String id = getSpecifiedId(); 117 118 if (id != null && getPage() != null && getPage().getRequestCycle() != null) 119 setClientId(getPage().getRequestCycle().getUniqueId(TapestryUtils.convertTapestryIdToNMToken(id))); 120 } 121 122 protected boolean evaluateCondition(IRequestCycle cycle, IForm form, boolean cycleRewinding) 123 { 124 boolean condition; 125 126 if (form == null || getVolatile()) 127 { 128 condition = getCondition(); 129 } 130 else 131 { 132 // we are in a form and we care -- load/store the condition in a hidden field 133 134 String name = form.getElementId(this); 135 136 if (!cycleRewinding) 137 { 138 condition = getCondition(); 139 writeValue(form, name, condition); 140 } 141 else 142 { 143 condition = readValue(cycle, name); 144 } 145 } 146 147 // write condition value if parameter is bound 148 149 IBinding conditionValueBinding = getConditionValueBinding(); 150 151 if (conditionValueBinding != null) 152 conditionValueBinding.setObject(new Boolean(condition)); 153 154 return condition; 155 } 156 157 private void writeValue(IForm form, String name, boolean value) 158 { 159 String externalValue; 160 161 Object booleanValue = new Boolean(value); 162 try 163 { 164 externalValue = getDataSqueezer().squeeze(booleanValue); 165 } 166 catch (Exception ex) 167 { 168 throw new ApplicationRuntimeException(Tapestry.format("If.unable-to-convert-value",booleanValue), this, null, ex); 169 } 170 171 form.addHiddenValue(name, externalValue); 172 } 173 174 private boolean readValue(IRequestCycle cycle, String name) 175 { 176 String submittedValue = cycle.getParameter(name); 177 178 _log.debug("readValue() with : " + name + " [" + submittedValue + "]"); 179 180 try 181 { 182 Object valueObject = getDataSqueezer().unsqueeze(submittedValue); 183 if (!(valueObject instanceof Boolean)) 184 throw new ApplicationRuntimeException(Tapestry.format("If.invalid-condition-type", submittedValue)); 185 186 return ((Boolean) valueObject).booleanValue(); 187 } 188 catch (Exception ex) 189 { 190 throw new ApplicationRuntimeException(Tapestry.format( 191 "If.unable-to-convert-string", 192 submittedValue), this, null, ex); 193 } 194 } 195 196 public abstract DataSqueezer getDataSqueezer(); 197 198 public boolean isDisabled() 199 { 200 return false; 201 } 202 203 /** 204 * Returns the value of the condition. 205 * 206 * @return the condition value 207 */ 208 public boolean getConditionValue() 209 { 210 if (!_rendering) 211 throw Tapestry.createRenderOnlyPropertyException(this, "conditionValue"); 212 213 return _conditionValue; 214 } 215 216 // Do nothing in those methods, but make the JVM happy 217 protected void renderFormComponent(IMarkupWriter writer, IRequestCycle cycle) 218 { 219 } 220 221 protected void rewindFormComponent(IMarkupWriter writer, IRequestCycle cycle) 222 { 223 } 224 225 /** 226 * For component can not take focus. 227 */ 228 protected boolean getCanTakeFocus() 229 { 230 return false; 231 } 232 }