001
014
015 package com.liferay.portal.kernel.util;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019
020 import java.io.IOException;
021 import java.io.Writer;
022
023 import java.lang.reflect.Constructor;
024
025
033 public class StringBundler {
034
035 public static final int UNSAFE_CREATE_THRESHOLD = GetterUtil.getInteger(
036 System.getProperty(
037 StringBundler.class.getName() + ".unsafe.create.threshold"));
038
039 public StringBundler() {
040 _array = new String[_DEFAULT_ARRAY_CAPACITY];
041 }
042
043 public StringBundler(int initialCapacity) {
044 if (initialCapacity <= 0) {
045 throw new IllegalArgumentException();
046 }
047
048 _array = new String[initialCapacity];
049 }
050
051 public StringBundler(String s) {
052 _array = new String[_DEFAULT_ARRAY_CAPACITY];
053
054 _array[0] = s;
055
056 _arrayIndex = 1;
057 }
058
059 public StringBundler(String[] stringArray) {
060 this(stringArray, 0);
061 }
062
063 public StringBundler(String[] stringArray, int extraSpace) {
064 _array = new String[stringArray.length + extraSpace];
065
066 for (int i = 0; i < stringArray.length; i++) {
067 String s = stringArray[i];
068
069 if ((s != null) && (s.length() > 0)) {
070 _array[_arrayIndex++] = s;
071 }
072 }
073 }
074
075 public StringBundler append(boolean b) {
076 if (b) {
077 return append(_TRUE);
078 }
079 else {
080 return append(_FALSE);
081 }
082 }
083
084 public StringBundler append(char c) {
085 return append(String.valueOf(c));
086 }
087
088 public StringBundler append(char[] charArray) {
089 if (charArray == null) {
090 return append("null");
091 }
092 else {
093 return append(new String(charArray));
094 }
095 }
096
097 public StringBundler append(double d) {
098 return append(Double.toString(d));
099 }
100
101 public StringBundler append(float f) {
102 return append(Float.toString(f));
103 }
104
105 public StringBundler append(int i) {
106 return append(Integer.toString(i));
107 }
108
109 public StringBundler append(long l) {
110 return append(Long.toString(l));
111 }
112
113 public StringBundler append(Object obj) {
114 return append(String.valueOf(obj));
115 }
116
117 public StringBundler append(String s) {
118 if (s == null) {
119 s = StringPool.NULL;
120 }
121
122 if (s.length() == 0) {
123 return this;
124 }
125
126 if (_arrayIndex >= _array.length) {
127 expandCapacity(_array.length * 2);
128 }
129
130 _array[_arrayIndex++] = s;
131
132 return this;
133 }
134
135 public StringBundler append(String[] stringArray) {
136 if ((stringArray == null) || (stringArray.length == 0)) {
137 return this;
138 }
139
140 if ((_array.length - _arrayIndex) < stringArray.length) {
141 expandCapacity((_array.length + stringArray.length) * 2);
142 }
143
144 for (int i = 0; i < stringArray.length; i++) {
145 String s = stringArray[i];
146
147 if ((s != null) && (s.length() > 0)) {
148 _array[_arrayIndex++] = s;
149 }
150 }
151
152 return this;
153 }
154
155 public StringBundler append(StringBundler sb) {
156 if ((sb == null) || (sb._arrayIndex == 0)) {
157 return this;
158 }
159
160 if ((_array.length - _arrayIndex) < sb._arrayIndex) {
161 expandCapacity((_array.length + sb._arrayIndex) * 2);
162 }
163
164 System.arraycopy(sb._array, 0, _array, _arrayIndex, sb._arrayIndex);
165
166 _arrayIndex += sb._arrayIndex;
167
168 return this;
169 }
170
171 public int capacity() {
172 return _array.length;
173 }
174
175 public int index() {
176 return _arrayIndex;
177 }
178
179 public int length() {
180 int length = 0;
181
182 for (int i = 0; i < _arrayIndex; i++) {
183 length += _array[i].length();
184 }
185
186 return length;
187 }
188
189 public void setIndex(int newIndex) {
190 if (newIndex < 0) {
191 throw new ArrayIndexOutOfBoundsException(newIndex);
192 }
193
194 if (newIndex > _array.length) {
195 String[] newArray = new String[newIndex];
196
197 System.arraycopy(_array, 0, newArray, 0, _arrayIndex);
198
199 _array = newArray;
200 }
201
202 if (_arrayIndex < newIndex) {
203 for (int i = _arrayIndex; i < newIndex; i++) {
204 _array[i] = StringPool.BLANK;
205 }
206 }
207
208 if (_arrayIndex > newIndex) {
209 for (int i = newIndex; i < _arrayIndex; i++) {
210 _array[i] = null;
211 }
212 }
213
214 _arrayIndex = newIndex;
215 }
216
217 public void setStringAt(String s, int index) {
218 if ((index < 0) || (index >= _arrayIndex)) {
219 throw new ArrayIndexOutOfBoundsException(index);
220 }
221
222 _array[index] = s;
223 }
224
225 public String stringAt(int index) {
226 if ((index < 0) || (index >= _arrayIndex)) {
227 throw new ArrayIndexOutOfBoundsException(index);
228 }
229
230 return _array[index];
231 }
232
233 public String toString() {
234 if (_arrayIndex == 0) {
235 return StringPool.BLANK;
236 }
237
238 if (_arrayIndex == 1) {
239 return _array[0];
240 }
241
242 if (_arrayIndex == 2) {
243 return _array[0].concat(_array[1]);
244 }
245
246 int length = 0;
247
248 for (int i = 0; i < _arrayIndex; i++) {
249 length += _array[i].length();
250 }
251
252 if ((_unsafeStringConstructor != null) &&
253 (length >= UNSAFE_CREATE_THRESHOLD)) {
254
255 return unsafeCreate(_array, _arrayIndex, length);
256 }
257 else if (_arrayIndex == 3) {
258 return _array[0].concat(_array[1]).concat(_array[2]);
259 }
260 else {
261 return safeCreate(_array, _arrayIndex, length);
262 }
263 }
264
265 public void writeTo(Writer writer) throws IOException {
266 for (int i = 0; i < _arrayIndex; i++) {
267 writer.write(_array[i]);
268 }
269 }
270
271 protected void expandCapacity(int newCapacity) {
272 String[] newArray = new String[newCapacity];
273
274 System.arraycopy(_array, 0, newArray, 0, _arrayIndex);
275
276 _array = newArray;
277 }
278
279 protected String safeCreate(String[] array, int index, int length) {
280 StringBuilder sb = new StringBuilder(length);
281
282 for (int i = 0; i < index; i++) {
283 sb.append(array[i]);
284 }
285
286 return sb.toString();
287 }
288
289 protected String unsafeCreate(String[] array, int index, int length) {
290 char[] charArray = new char[length];
291
292 int offset = 0;
293
294 for (int i = 0; i < index; i++) {
295 String s = array[i];
296
297 s.getChars(0, s.length(), charArray, offset);
298
299 offset += s.length();
300 }
301
302 try {
303 return _unsafeStringConstructor.newInstance(0, length, charArray);
304 }
305 catch (Exception e) {
306 throw new IllegalStateException(e);
307 }
308 }
309
310 private static final int _DEFAULT_ARRAY_CAPACITY = 16;
311
312 private static final String _FALSE = "false";
313
314 private static final String _TRUE = "true";
315
316 private static Log _log = LogFactoryUtil.getLog(StringBundler.class);
317
318 private static Constructor<String> _unsafeStringConstructor;
319
320 static {
321 if (UNSAFE_CREATE_THRESHOLD > 0) {
322 try {
323 _unsafeStringConstructor = String.class.getDeclaredConstructor(
324 int.class, int.class, char[].class);
325
326 _unsafeStringConstructor.setAccessible(true);
327 }
328 catch (Exception e) {
329 _log.error(e, e);
330 }
331 }
332 }
333
334 private String[] _array;
335 private int _arrayIndex;
336
337 }