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 015package org.apache.tapestry.contrib.form; 016 017import org.apache.hivemind.ApplicationRuntimeException; 018import org.apache.hivemind.HiveMind; 019import org.apache.tapestry.AbstractComponent; 020import org.apache.tapestry.IActionListener; 021import org.apache.tapestry.IForm; 022import org.apache.tapestry.IMarkupWriter; 023import org.apache.tapestry.IRequestCycle; 024import org.apache.tapestry.Tapestry; 025import org.apache.tapestry.TapestryUtils; 026import org.apache.tapestry.form.IFormComponent; 027import org.apache.tapestry.listener.ListenerInvoker; 028import 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 041public 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}