1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.myfaces.trinidad.util;
20
21 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
22
23 /**
24 * The FastMessageFormat class is a greatly reduced version
25 * of the java.text.MessageFormat class. It's also much faster
26 * and much less expensive to create, which is especially
27 * valuable when it is created and thrown away many times -
28 * a common use case in web applications.
29 * <p>
30 * The only syntax supported by this class is simple index-based
31 * replacement, namely:
32 * <pre>
33 * some{1}text{0}here{2}andthere
34 * </pre>
35 * as well as escaping using single quotes. Like MessageFormat,
36 * a single quote must be represented using two consecutive single
37 * quotes, but the contents of any text between single quotes
38 * will not be interpreted. So, the following pattern could
39 * be used to include a left bracket:
40 * <pre>
41 * some'{'text{0}
42 * </pre>
43 * <p>
44 * @version $Name: $ ($Revision: adfrt/faces/adf-faces-api/src/main/java/oracle/adf/view/faces/util/FastMessageFormat.java#0 $) $Date: 10-nov-2005.19:08:37 $
45 */
46 public class FastMessageFormat
47 {
48 /**
49 * Creates a FastMessageFormat based on the given format string.
50 */
51 public FastMessageFormat(String formatString)
52 {
53 if (formatString == null)
54 throw new NullPointerException();
55
56 _formatText = formatString.toCharArray();
57 }
58
59
60 /**
61 * Formats the given array of strings based on the initial
62 * pattern. It is legal for this array to be shorter
63 * than that indicated by the pattern, or to have null
64 * entries - these will simply be ignored.
65 * <p>
66 * @param source an array of strings
67 */
68 public String format(Object[] source)
69 {
70 int formatLength = _formatText.length;
71 int length = 0;
72 int sourceCount = source.length;
73 for (int i = 0; i < sourceCount; i++)
74 {
75 Object sourceString = source[i];
76 if (sourceString != null)
77 {
78 length += sourceString.toString().length();
79 }
80 }
81
82 StringBuffer buffer = new StringBuffer(length + formatLength);
83
84 int lastStart = 0;
85 boolean inQuote = false;
86 for (int i = 0; i < formatLength; i++)
87 {
88 char ch = _formatText[i];
89 if (inQuote)
90 {
91 if (ch == '\'')
92 {
93 buffer.append(_formatText, lastStart, i - lastStart);
94 i++;
95 lastStart = i;
96 inQuote = false;
97 }
98 }
99 else
100 {
101 if (ch == '\'')
102 {
103 buffer.append(_formatText, lastStart, i - lastStart);
104 i++;
105 lastStart = i;
106
107 // Check for doubled-up quotes
108 if ((i < formatLength) && (_formatText[i] == '\''))
109 {
110 // Do nothing; we'll add the doubled-up quote later
111 ;
112 }
113 else
114 {
115 inQuote = true;
116 }
117 }
118 else if (ch == '{')
119 {
120 buffer.append(_formatText, lastStart, i - lastStart);
121
122 int sourceIndex = 0;
123 int j = i + 1;
124 for (; j < formatLength; j++)
125 {
126 char patternChar = _formatText[j];
127 if (patternChar == '}')
128 {
129 break;
130 }
131 else
132 {
133 if ((patternChar < '0') ||
134 (patternChar > '9'))
135 throw new IllegalArgumentException(_LOG.getLogger().getResourceBundle().getString(
136 "FASTMESSAGEFORMAT_ONLY_SUPPORT_NUMERIC_ARGUMENTS"));
137 sourceIndex = (sourceIndex * 10) + (patternChar - '0');
138 }
139 }
140
141 if (j == formatLength)
142 throw new IllegalArgumentException(_LOG.getLogger().getResourceBundle().getString(
143 "END_OF_PATTERN_NOT_FOUND"));
144 if (j == i + 1)
145 throw new IllegalArgumentException(_LOG.getLogger().getResourceBundle().getString(
146 "FASTMESSAGEFORMAT_FIND_EMPTY_ARGUMENT"));
147 if (sourceIndex < sourceCount)
148 {
149 Object sourceString = source[sourceIndex];
150 if (sourceString != null)
151 buffer.append(sourceString.toString());
152 }
153
154 i = j;
155 lastStart = i + 1;
156 }
157 else
158 {
159 // Do nothing. The character will be added in later
160 ;
161 }
162 }
163 }
164
165 buffer.append(_formatText, lastStart, formatLength - lastStart);
166
167 return new String(buffer);
168 }
169
170 private final char[] _formatText;
171 private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(
172 FastMessageFormat.class);
173 }
174
175
176
177