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.html;
020:
021: import org.apache.beehive.netui.util.internal.InternalStringBuilder;
022:
023: import org.apache.beehive.netui.util.Bundle;
024:
025: import javax.servlet.jsp.JspException;
026: import javax.servlet.jsp.tagext.JspTag;
027: import javax.servlet.jsp.tagext.SimpleTagSupport;
028:
029: //java imports
030:
031: //internal imports
032:
033: //external imports
034:
035: /**
036: * A formatter used to format strings. FormatString uses the following pattern syntax:
037: * <p>
038: * The '#' character gets replaced by the next character in the string getting formatted,
039: * while other characters get put in as literals. For example:
040: * <p>
041: * String "5555555555" with pattern "(###)###-####" would result in: (555)555-5555.
042: * <p>
043: * The '*' character will display all characters in the string at that point in the pattern. For example:
044: * <p>
045: * String "123456" with pattern "#-*!" would result in: 1-23456!
046: * <p>
047: * If a result with a '#' pr '*' character showing is desired, the '#' or '*' needs to
048: * be escaped with the '$' character. For example:
049: * <p>
050: * String "ABCD" with pattern "$#-####" would result in: #-ABCD.
051: * <p>
052: * To show a '$' in the result, the '$' character needs to be escaped. For example:
053: * <p>
054: * String "1234" with pattern "$$#,###" would result in: $1,234
055: * <p>
056: * If the truncate attribute is set to "true", characters in the string that exceed the pattern
057: * will be dropped. Otherwise, they will be appended to the end of the formatted string.
058: * @jsptagref.tagdescription A formatter used to format strings.
059: *
060: * <p>The <netui:formatString> tag formats the output of its parent tag. For example:
061: *
062: * <pre> <netui:span value="${pageFlow.phone}">
063: * <netui:formatString pattern="phone number: (###) ###-####"/>
064: * </netui:span> </pre>
065: *
066: * <p>
067: * <netui:formatString> uses the following pattern syntax:
068: * <p>
069: * The <b>#</b> character is a placeholder for individual characters in the String to be formatted,
070: * while other characters are treated as literals. For example:
071: * <p>
072: * String "5555555555" with pattern "(###)###-####" would result in: (555)555-5555.
073: * <p>
074: * The <b>*</b> character displays all remaining characters in the String. For example:
075: * <p>
076: * String "123456" with pattern "#-*!" would result in: 1-23456!
077: * <p>
078: * If a result with a '#' or '*' character showing is desired, the '#' or '*' needs to
079: * be escaped with the '$' character. For example:
080: * <p>
081: * String "ABCD" with pattern "$#-####" would result in: #-ABCD.
082: * <p>
083: * To show a '$' in the result, the '$' character needs to be escaped. For example:
084: * <p>
085: * String "1234" with pattern "$$#,###" would result in: $1,234
086: * <p>
087: * If the <code>truncate</code> attribute is set to "true", characters in the String that exceed the pattern
088: * will be dropped. Otherwise, they will be appended to the end of the formatted String.
089: * @example In this sample, the String "2125555555" will be formatted to this form: (212)555-5555.
090: *
091: * <pre> <netui:span value="2125555555">
092: * <netui:formatString pattern="phone (###) ###-####"/>
093: * </netui:span> </pre>
094: * @netui:tag name="formatString" body-content="empty" description="A formatter used to format strings."
095: * @netui:attribute name="pattern" required="true" rtexprvalue="true"
096: */
097: public class FormatString extends FormatTag {
098: protected boolean truncate = false; // Whether or not pattern-exceeding characters should be dropped.
099:
100: /**
101: * Return the name of the Tag.
102: */
103: public String getTagName() {
104: return "FormatString";
105: }
106:
107: /**
108: * Sets whether or not pattern-exceeding characters should be dropped.
109: * @param truncate "true" or "false"
110: * @jsptagref.attributedescription A boolean specifying whether characters that exceed the pattern's length should be dropped.
111: * @jsptagref.databindable false
112: * @jsptagref.attributesyntaxvalue <i>boolean_truncate</i>
113: * @netui:attribute required="false" rtexprvalue="true"
114: * description="A boolean specifying whether characters that exceed the pattern's length should be dropped."
115: */
116: public void setTruncate(boolean truncate) {
117: this .truncate = truncate;
118: }
119:
120: /**
121: * Create the internal Formatter instance and perform the formatting.
122: * @throws JspException if a JSP exception has occurred
123: */
124: public void doTag() throws JspException {
125: JspTag parentTag = SimpleTagSupport.findAncestorWithClass(this ,
126: IFormattable.class);
127:
128: // if there are errors we need to either add these to the parent AbstractBastTag or report an error.
129: if (hasErrors()) {
130: if (parentTag instanceof IFormattable) {
131: IFormattable parent = (IFormattable) parentTag;
132: parent.formatterHasError();
133: }
134: reportErrors();
135: return;
136: }
137:
138: if (parentTag instanceof IFormattable) {
139: StringFormatter formatter = new StringFormatter();
140: formatter.setPattern(_pattern);
141: formatter.setTruncate(truncate);
142: IFormattable parent = (IFormattable) parentTag;
143: parent.addFormatter(formatter);
144: } else {
145: String s = Bundle
146: .getString("Tags_FormattableParentRequired");
147: registerTagError(s, null);
148: reportErrors();
149: }
150: }
151:
152: /**
153: * Internal FormatTag.Formatter which performs its own string parsing and formatting.
154: */
155: public static class StringFormatter extends FormatTag.Formatter {
156: private boolean truncate;
157:
158: public boolean getTruncate() {
159: return truncate;
160: }
161:
162: public void setTruncate(boolean truncate) {
163: this .truncate = truncate;
164: }
165:
166: public String format(Object dataToFormat) throws JspException {
167: if (dataToFormat == null) {
168: return null;
169: }
170: InternalStringBuilder formattedString = new InternalStringBuilder(
171: 32);
172: int index = 0;
173: int patternIndex = 0;
174: String unformattedString = dataToFormat.toString();
175:
176: int length = unformattedString.length();
177: int patternLength = getPattern().length();
178:
179: int ignoreNumbers = 0;
180:
181: //Cycle through each character in the string
182: for (index = 0; index < length; index++) {
183: if (patternIndex < patternLength) {
184: boolean loop = true;
185: while (loop) {
186: char this Char = getPattern().charAt(
187: patternIndex);
188: if (this Char == '#')
189: break;
190: else if (this Char == '*') {
191: ignoreNumbers++;
192: break;
193: } else if (this Char == '$') {
194: if ((patternIndex + 1 < patternLength)
195: && (getPattern().charAt(
196: patternIndex + 1) == '$')) {
197: patternIndex++;
198: } else if ((patternIndex + 1 < patternLength)
199: && (getPattern().charAt(
200: patternIndex + 1) == '#')) {
201: patternIndex++;
202: } else if ((patternIndex + 1 < patternLength)
203: && (getPattern().charAt(
204: patternIndex + 1) == '*')) {
205: patternIndex++;
206: }
207: }
208: formattedString = formattedString
209: .append(getPattern().charAt(
210: patternIndex));
211: patternIndex++;
212: if (patternIndex >= patternLength)
213: loop = false;
214: }
215: }
216:
217: if ((patternIndex >= patternLength) && (truncate))
218: break;
219:
220: if (ignoreNumbers == 1) {
221: formattedString.append(unformattedString
222: .substring(index));
223: ignoreNumbers++;
224: } else if (ignoreNumbers > 1) {
225: //Ignore
226: } else {
227: formattedString.append(unformattedString
228: .charAt(index));
229: }
230: patternIndex++;
231: }
232:
233: if (patternIndex < patternLength) {
234: //Throw in the rest of the pattern
235: while (patternIndex < patternLength) {
236: char patternChar = getPattern()
237: .charAt(patternIndex);
238: if (patternChar == '#') {
239: formattedString.append(" ");
240: } else {
241: formattedString.append(patternChar);
242: }
243: patternIndex++;
244: }
245: }
246: return formattedString.toString();
247: }
248: }
249: }
|