001/** 002 * 003 * Copyright 2014 Florian Schmaus 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * 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 */ 017package org.jivesoftware.smack.util; 018 019import java.util.ArrayList; 020import java.util.List; 021 022public class LazyStringBuilder implements Appendable, CharSequence { 023 024 private final List<CharSequence> list; 025 026 private String cache; 027 028 private void invalidateCache() { 029 cache = null; 030 } 031 032 public LazyStringBuilder() { 033 list = new ArrayList<CharSequence>(20); 034 } 035 036 public LazyStringBuilder append(LazyStringBuilder lsb) { 037 list.addAll(lsb.list); 038 invalidateCache(); 039 return this; 040 } 041 042 @Override 043 public LazyStringBuilder append(CharSequence csq) { 044 assert csq != null; 045 list.add(csq); 046 invalidateCache(); 047 return this; 048 } 049 050 @Override 051 public LazyStringBuilder append(CharSequence csq, int start, int end) { 052 CharSequence subsequence = csq.subSequence(start, end); 053 list.add(subsequence); 054 invalidateCache(); 055 return this; 056 } 057 058 @Override 059 public LazyStringBuilder append(char c) { 060 list.add(Character.toString(c)); 061 invalidateCache(); 062 return this; 063 } 064 065 @Override 066 public int length() { 067 if (cache != null) { 068 return cache.length(); 069 } 070 int length = 0; 071 for (CharSequence csq : list) { 072 length += csq.length(); 073 } 074 return length; 075 } 076 077 @Override 078 public char charAt(int index) { 079 if (cache != null) { 080 return cache.charAt(index); 081 } 082 for (CharSequence csq : list) { 083 if (index < csq.length()) { 084 return csq.charAt(index); 085 } else { 086 index -= csq.length(); 087 } 088 } 089 throw new IndexOutOfBoundsException(); 090 } 091 092 @Override 093 public CharSequence subSequence(int start, int end) { 094 return toString().subSequence(start, end); 095 } 096 097 @Override 098 public String toString() { 099 if (cache == null) { 100 StringBuilder sb = new StringBuilder(length()); 101 for (CharSequence csq : list) { 102 sb.append(csq); 103 } 104 cache = sb.toString(); 105 } 106 return cache; 107 } 108}