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