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.Collection; 020 021import org.jivesoftware.smack.packet.Element; 022import org.jivesoftware.smack.packet.NamedElement; 023import org.jivesoftware.smack.packet.ExtensionElement; 024 025public class XmlStringBuilder implements Appendable, CharSequence { 026 public static final String RIGHT_ANGLE_BRACKET = Character.toString('>'); 027 028 private final LazyStringBuilder sb; 029 030 public XmlStringBuilder() { 031 sb = new LazyStringBuilder(); 032 } 033 034 public XmlStringBuilder(ExtensionElement pe) { 035 this(); 036 prelude(pe); 037 } 038 039 public XmlStringBuilder(NamedElement e) { 040 this(); 041 halfOpenElement(e.getElementName()); 042 } 043 044 public XmlStringBuilder escapedElement(String name, String escapedContent) { 045 assert escapedContent != null; 046 openElement(name); 047 append(escapedContent); 048 closeElement(name); 049 return this; 050 } 051 052 /** 053 * 054 * @param name 055 * @param content 056 * @return the XmlStringBuilder 057 */ 058 public XmlStringBuilder element(String name, String content) { 059 assert content != null; 060 openElement(name); 061 escape(content); 062 closeElement(name); 063 return this; 064 } 065 066 public XmlStringBuilder element(String name, Enum<?> content) { 067 assert content != null; 068 element(name, content.name()); 069 return this; 070 } 071 072 public XmlStringBuilder element(Element element) { 073 assert element != null; 074 return append(element.toXML()); 075 } 076 077 public XmlStringBuilder optElement(String name, String content) { 078 if (content != null) { 079 element(name, content); 080 } 081 return this; 082 } 083 084 public XmlStringBuilder optElement(Element element) { 085 if (element != null) { 086 append(element.toXML()); 087 } 088 return this; 089 } 090 091 public XmlStringBuilder optElement(String name, Enum<?> content) { 092 if (content != null) { 093 element(name, content); 094 } 095 return this; 096 } 097 098 public XmlStringBuilder optIntElement(String name, int value) { 099 if (value >= 0) { 100 element(name, String.valueOf(value)); 101 } 102 return this; 103 } 104 105 public XmlStringBuilder halfOpenElement(String name) { 106 assert(StringUtils.isNotEmpty(name)); 107 sb.append('<').append(name); 108 return this; 109 } 110 111 public XmlStringBuilder halfOpenElement(NamedElement namedElement) { 112 return halfOpenElement(namedElement.getElementName()); 113 } 114 115 public XmlStringBuilder openElement(String name) { 116 halfOpenElement(name).rightAngleBracket(); 117 return this; 118 } 119 120 public XmlStringBuilder closeElement(String name) { 121 sb.append("</").append(name); 122 rightAngleBracket(); 123 return this; 124 } 125 126 public XmlStringBuilder closeElement(NamedElement e) { 127 closeElement(e.getElementName()); 128 return this; 129 } 130 131 public XmlStringBuilder closeEmptyElement() { 132 sb.append("/>"); 133 return this; 134 } 135 136 /** 137 * Add a right angle bracket '>' 138 * 139 * @return a reference to this object. 140 */ 141 public XmlStringBuilder rightAngleBracket() { 142 sb.append(RIGHT_ANGLE_BRACKET); 143 return this; 144 } 145 146 /** 147 * 148 * @return a reference to this object 149 * @deprecated use {@link #rightAngleBracket()} instead 150 */ 151 @Deprecated 152 public XmlStringBuilder rightAngelBracket() { 153 return rightAngleBracket(); 154 } 155 156 /** 157 * Does nothing if value is null. 158 * 159 * @param name 160 * @param value 161 * @return the XmlStringBuilder 162 */ 163 public XmlStringBuilder attribute(String name, String value) { 164 assert value != null; 165 sb.append(' ').append(name).append("='"); 166 escape(value); 167 sb.append('\''); 168 return this; 169 } 170 171 public XmlStringBuilder attribute(String name, Enum<?> value) { 172 assert value != null; 173 attribute(name, value.name()); 174 return this; 175 } 176 177 public XmlStringBuilder attribute(String name, int value) { 178 assert name != null; 179 return attribute(name, String.valueOf(value)); 180 } 181 182 public XmlStringBuilder optAttribute(String name, String value) { 183 if (value != null) { 184 attribute(name, value); 185 } 186 return this; 187 } 188 189 public XmlStringBuilder optAttribute(String name, Enum<?> value) { 190 if (value != null) { 191 attribute(name, value.toString()); 192 } 193 return this; 194 } 195 196 /** 197 * Add the given attribute if value => 0 198 * 199 * @param name 200 * @param value 201 * @return a reference to this object 202 */ 203 public XmlStringBuilder optIntAttribute(String name, int value) { 204 if (value >= 0) { 205 attribute(name, Integer.toString(value)); 206 } 207 return this; 208 } 209 210 /** 211 * Add the given attribute if value not null and value => 0. 212 * 213 * @param name 214 * @param value 215 * @return a reference to this object 216 */ 217 public XmlStringBuilder optLongAttribute(String name, Long value) { 218 if (value != null && value >= 0) { 219 attribute(name, Long.toString(value)); 220 } 221 return this; 222 } 223 224 public XmlStringBuilder optBooleanAttribute(String name, boolean bool) { 225 if (bool) { 226 sb.append(' ').append(name).append("='true'"); 227 } 228 return this; 229 } 230 231 public XmlStringBuilder xmlnsAttribute(String value) { 232 optAttribute("xmlns", value); 233 return this; 234 } 235 236 public XmlStringBuilder xmllangAttribute(String value) { 237 optAttribute("xml:lang", value); 238 return this; 239 } 240 241 public XmlStringBuilder escape(String text) { 242 assert text != null; 243 sb.append(StringUtils.escapeForXML(text)); 244 return this; 245 } 246 247 public XmlStringBuilder prelude(ExtensionElement pe) { 248 return prelude(pe.getElementName(), pe.getNamespace()); 249 } 250 251 public XmlStringBuilder prelude(String elementName, String namespace) { 252 halfOpenElement(elementName); 253 xmlnsAttribute(namespace); 254 return this; 255 } 256 257 public XmlStringBuilder optAppend(CharSequence csq) { 258 if (csq != null) { 259 append(csq); 260 } 261 return this; 262 } 263 264 public XmlStringBuilder optAppend(Element element) { 265 if (element != null) { 266 append(element.toXML()); 267 } 268 return this; 269 } 270 271 public XmlStringBuilder append(XmlStringBuilder xsb) { 272 assert xsb != null; 273 sb.append(xsb.sb); 274 return this; 275 } 276 277 public XmlStringBuilder append(Collection<? extends Element> elements) { 278 for (Element element : elements) { 279 append(element.toXML()); 280 } 281 return this; 282 } 283 284 public XmlStringBuilder emptyElement(Enum<?> element) { 285 return emptyElement(element.name()); 286 } 287 288 public XmlStringBuilder emptyElement(String element) { 289 halfOpenElement(element); 290 return closeEmptyElement(); 291 } 292 293 public XmlStringBuilder condEmptyElement(boolean condition, String element) { 294 if (condition) { 295 emptyElement(element); 296 } 297 return this; 298 } 299 300 public XmlStringBuilder condAttribute(boolean condition, String name, String value) { 301 if (condition) { 302 attribute(name, value); 303 } 304 return this; 305 } 306 307 @Override 308 public XmlStringBuilder append(CharSequence csq) { 309 assert csq != null; 310 sb.append(csq); 311 return this; 312 } 313 314 @Override 315 public XmlStringBuilder append(CharSequence csq, int start, int end) { 316 assert csq != null; 317 sb.append(csq, start, end); 318 return this; 319 } 320 321 @Override 322 public XmlStringBuilder append(char c) { 323 sb.append(c); 324 return this; 325 } 326 327 @Override 328 public int length() { 329 return sb.length(); 330 } 331 332 @Override 333 public char charAt(int index) { 334 return sb.charAt(index); 335 } 336 337 @Override 338 public CharSequence subSequence(int start, int end) { 339 return sb.subSequence(start, end); 340 } 341 342 @Override 343 public String toString() { 344 return sb.toString(); 345 } 346 347 @Override 348 public boolean equals(Object other) { 349 if (!(other instanceof CharSequence)) { 350 return false; 351 } 352 CharSequence otherCharSequenceBuilder = (CharSequence) other; 353 return toString().equals(otherCharSequenceBuilder.toString()); 354 } 355 356 @Override 357 public int hashCode() { 358 return toString().hashCode(); 359 } 360}