001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: * $Header:$
018: */
019: package org.apache.beehive.netui.tags.databinding.repeater.pad;
020:
021: import javax.servlet.jsp.JspException;
022:
023: import org.apache.beehive.netui.tags.databinding.repeater.RepeaterComponent;
024: import org.apache.beehive.netui.util.Bundle;
025: import org.apache.beehive.netui.util.logging.Logger;
026:
027: /**
028: * Sets the number of items rendered by a {@link org.apache.beehive.netui.tags.databinding.repeater.Repeater} tag.
029: * The <netui-data:pad> tag has the ability to turn an irregular data set in the <netui-data:repeater> tag
030: * into a regular data set through the use of the three attributes:
031: * <blockquote>
032: * <ul>
033: * <li><code>maxRepeat</code> - truncates the rendering of the data set</li>
034: * <li><code>minRepeat</code> - forces the <netui-data:repeater> to render
035: * a minimum number of elements</li>
036: * <li><code>padText</code> - default text to render if the data set does not have the
037: * minimum number of elements</li>
038: * </ul>
039: * </blockquote>
040: * If the <code>padText</code> attribute is unset, the body of the <netui-data:pad> tag is used as the default text.
041: * </p>
042: * <p>
043: * Note, the <code>container</code> data binding context should not be used inside of the Pad's <code>padText</code>
044: * attribute as binding to both the <code>item</code> and <code>index</code> could product unexpected results.
045: * </p>
046: * <p>
047: * In the following example, assume that the <netui-data:repeater> tag iterates over a {@link java.util.List} object.
048: * The <netui-data:pad> limits the iteration to three cycles, no matter how many elements are actually in the List.
049: * <pre>
050: * <netui-data:repeater dataSource="pageFlow.myList">
051: * <netui-data:pad maxRepeat="3"/>
052: * <netui-data:repeaterItem>
053: * <netui:span value="${container.item}" />
054: * </netui-data:repeaterItem>
055: * </netui-data:repeater>
056: * </pre>
057: * </p>
058: *
059: * @jsptagref.tagdescription <p>
060: * Sets the number of items rendered by a {@link org.apache.beehive.netui.tags.databinding.repeater.Repeater} tag.
061: * The <netui-data:pad> tag has the ability to turn an irregular data set in the <netui-data:repeater> tag
062: * into a regular data set through the use of the three attributes:
063: * <blockquote>
064: * <ul>
065: * <li><code>maxRepeat</code> - truncates the rendering of the data set</li>
066: * <li><code>minRepeat</code> - forces the <netui-data:repeater> to render
067: * a minimum number of elements</li>
068: * <li><code>padText</code> - default text to render if the data set does not have the
069: * minimum number of elements</li>
070: * </ul>
071: * </blockquote>
072: * If the <code>padText</code> attribute is unset, the body of the <netui-data:pad> tag is used as the default text.
073: * </p>
074: * <p>
075: * Note, the <code>container</code> data binding context should not be used inside of the Pad's <code>padText</code>
076: * attribute as binding to both the <code>item</code> and <code>index</code> could product unexpected results.
077: * </p>
078: *
079: * @example
080: * <p>
081: * In the following example, assume that the <netui-data:repeater> tag iterates over a {@link java.util.List} object.
082: * The <netui-data:pad> limits the iteration to three cycles, no matter how many elements are actually in the List.
083: * <pre>
084: * <netui-data:repeater dataSource="pageFlow.myList">
085: * <netui-data:pad maxRepeat="3"/>
086: * <netui-data:repeaterItem>
087: * <netui:span value="${container.item}" />
088: * </netui-data:repeaterItem>
089: * </netui-data:repeater>
090: * </pre>
091: * </p>
092: *
093: * @netui:tag name="pad"
094: * description="Repeater tag set tag that can pad an irregularly side data set in order to force the repeater to render a regular number of rows"
095: */
096: public class Pad extends RepeaterComponent {
097:
098: private static final Logger LOGGER = Logger.getInstance(Pad.class);
099:
100: private String _padText = null;
101: private Integer _maxRepeat = null;
102: private Integer _minRepeat = null;
103:
104: /**
105: * Get the name of this tag. This is used to identify the type of this tag
106: * for reporting tag errors.
107: *
108: * @return a constant String representing the name of this tag.
109: */
110: public String getTagName() {
111: return "Pad";
112: }
113:
114: /**
115: * Set the text that will be used when padding a {@link org.apache.beehive.netui.tags.databinding.repeater.Repeater}
116: * that renders its body too few times.
117: *
118: * @param padText the text that is used to pad a repeater's content
119: * @jsptagref.attributedescription
120: * Set the text that will be used when padding a {@link org.apache.beehive.netui.tags.databinding.repeater.Repeater}
121: * that renders its body too few times.
122: * @jsptagref.attributesyntaxvalue <i>string_padText</i>
123: * @netui:attribute required="false" rtexprvalue="true"
124: */
125: public void setPadText(String padText) {
126: _padText = padText;
127: }
128:
129: /**
130: * Set the maximum number of items that will be rendered by a <netui-data:repeater> tag. If the size
131: * of the data set is greater than this, only this many items will be rendered. This value can be an integer
132: * or can be an expression that resolves to an integer.
133: *
134: * @param maxRepeat an integer or an expression that references an integer for the maximum number of items to render
135: * @jsptagref.attributedescription
136: * Set the maximum number of items that will be rendered by a <netui-data:repeater> tag. If the size
137: * of the data set is greater than this, only this many items will be rendered. This value can be an integer
138: * or can be an expression that resolves to an integer.
139: * @jsptagref.attributesyntaxvalue <i>integer_or_expression_maxRepeat</i>
140: * @netui:attribute required="false" rtexprvalue="true"
141: */
142: public void setMaxRepeat(int maxRepeat) {
143: _maxRepeat = new Integer(maxRepeat);
144: }
145:
146: /**
147: *
148: * @param minRepeat an integer or an expression that references an integer for the minimum number of items to render
149: * @jsptagref.attributedescription
150: * Set the minimum number of items that will be rendered by a <netui-data:repeater> tag. If the size of
151: * the data set is smaller than this, the data set will be padded with the value of the <code>padText</code>
152: * attribute. This value can be an integer or can be an expression that resolves to an integer.
153: * @jsptagref.attributesyntaxvalue <i>integer_or_expression_minRepeat</i>
154: * @netui:attribute required="false" rtexprvalue="true"
155: */
156: public void setMinRepeat(int minRepeat) {
157: _minRepeat = new Integer(minRepeat);
158: }
159:
160: protected boolean shouldRender() {
161: if (_padText == null)
162: return true;
163: else
164: return false;
165: }
166:
167: public int doAfterBody() throws JspException {
168: return SKIP_BODY;
169: }
170:
171: /**
172: * Complete rendering the body of this tag. If the padText property was unset,
173: * the body of the tag is used as the pad text.
174: *
175: * @param state the current render state of the Repeater
176: * @return EVAL_PAGE
177: * @throws JspException if an error occurs that can not be reported on the page
178: */
179: protected int renderEndTag(int state) throws JspException {
180:
181: if (_padText == null && bodyContent != null) {
182: _padText = bodyContent.getString();
183: }
184:
185: if (hasErrors()) {
186: reportErrors();
187: localRelease();
188: return EVAL_PAGE;
189: }
190:
191: PadContext pc = new PadContext(_padText,
192: (_minRepeat != null ? _minRepeat.intValue()
193: : PadContext.DEFAULT_VALUE),
194: (_maxRepeat != null ? _maxRepeat.intValue()
195: : PadContext.DEFAULT_VALUE));
196:
197: getRepeater().setPadContext(pc);
198:
199: return EVAL_PAGE;
200: }
201:
202: /**
203: * Reset all of the fields of this tag.
204: */
205: protected void localRelease() {
206: super .localRelease();
207: if (bodyContent != null)
208: bodyContent.clearBody();
209: _padText = null;
210: _maxRepeat = null;
211: _minRepeat = null;
212: }
213:
214: /**
215: * Verify that the attributes set on the tag are correct. Check:
216: * <ul>
217: * <li>The minRepeat value can be converted into an integer</li>
218: * <li>The maxRepeat value can be converted into an integer</li>
219: * <li>The minRepeat value is less than or equal to the maxRepeat value</li>
220: * </ul>
221: *
222: * @throws JspException if an error occurs that can not be reported on the page
223: */
224: protected void verifyAttributes() throws JspException {
225: if (_maxRepeat != null && _maxRepeat.intValue() <= 0) {
226: String msg = Bundle.getErrorString("Tags_Pad_intTooSmall",
227: new Object[] { _maxRepeat, "maxRepeat" });
228: getRepeater().registerTagError(msg, null);
229: }
230:
231: if (_minRepeat != null && _minRepeat.intValue() <= 0) {
232: String msg = Bundle.getErrorString(
233: "Tags_Pad_minRepeatIntTooSmall", new Object[] {
234: _minRepeat, "minRepeat" });
235: getRepeater().registerTagError(msg, null);
236: }
237:
238: // check composite properties
239: if (_maxRepeat != null && _minRepeat != null
240: && _minRepeat.intValue() > _maxRepeat.intValue()) {
241: if (LOGGER.isWarnEnabled()) {
242: String msg = "The value of maxRepeat ("
243: + _maxRepeat
244: + ") must be greater than the value of minRepeat ("
245: + _minRepeat + ") on the Repeater Pad tag.";
246: LOGGER.warn(msg);
247: }
248:
249: String msg = Bundle.getErrorString(
250: "Tags_Pad_minGreaterThanMax", new Object[] {
251: _maxRepeat, _minRepeat });
252: getRepeater().registerTagError(msg, null);
253: }
254: }
255: }
|