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 org.jivesoftware.smack.packet.PacketExtension; 020 021public class XmlStringBuilder implements Appendable, CharSequence { 022 public static final String RIGHT_ANGEL_BRACKET = Character.toString('>'); 023 024 private final LazyStringBuilder sb; 025 026 public XmlStringBuilder() { 027 sb = new LazyStringBuilder(); 028 } 029 030 public XmlStringBuilder(PacketExtension pe) { 031 this(); 032 prelude(pe); 033 } 034 035 /** 036 * Does nothing if content is null. 037 * 038 * @param name 039 * @param content 040 * @return the XmlStringBuilder 041 */ 042 public XmlStringBuilder element(String name, String content) { 043 assert content != null; 044 openElement(name); 045 escape(content); 046 closeElement(name); 047 return this; 048 } 049 050 public XmlStringBuilder element(String name, Enum<?> content) { 051 assert content != null; 052 element(name, content.name()); 053 return this; 054 } 055 056 public XmlStringBuilder optElement(String name, String content) { 057 if (content != null) { 058 element(name, content); 059 } 060 return this; 061 } 062 063 public XmlStringBuilder optElement(String name, Enum<?> content) { 064 if (content != null) { 065 element(name, content); 066 } 067 return this; 068 } 069 070 public XmlStringBuilder halfOpenElement(String name) { 071 sb.append('<').append(name); 072 return this; 073 } 074 075 public XmlStringBuilder openElement(String name) { 076 halfOpenElement(name).rightAngelBracket(); 077 return this; 078 } 079 080 public XmlStringBuilder closeElement(String name) { 081 sb.append("</").append(name); 082 rightAngelBracket(); 083 return this; 084 } 085 086 public XmlStringBuilder closeElement(PacketExtension pe) { 087 closeElement(pe.getElementName()); 088 return this; 089 } 090 091 public XmlStringBuilder closeEmptyElement() { 092 sb.append("/>"); 093 return this; 094 } 095 096 public XmlStringBuilder rightAngelBracket() { 097 sb.append(RIGHT_ANGEL_BRACKET); 098 return this; 099 } 100 101 /** 102 * Does nothing if value is null. 103 * 104 * @param name 105 * @param value 106 * @return the XmlStringBuilder 107 */ 108 public XmlStringBuilder attribute(String name, String value) { 109 assert value != null; 110 sb.append(' ').append(name).append("='"); 111 escape(value); 112 sb.append('\''); 113 return this; 114 } 115 116 public XmlStringBuilder attribute(String name, Enum<?> value) { 117 assert value != null; 118 attribute(name, value.name()); 119 return this; 120 } 121 122 public XmlStringBuilder optAttribute(String name, String value) { 123 if (value != null) { 124 attribute(name, value); 125 } 126 return this; 127 } 128 129 public XmlStringBuilder optAttribute(String name, Enum<?> value) { 130 if (value != null) { 131 attribute(name, value.name()); 132 } 133 return this; 134 } 135 136 public XmlStringBuilder xmlnsAttribute(String value) { 137 optAttribute("xmlns", value); 138 return this; 139 } 140 141 public XmlStringBuilder xmllangAttribute(String value) { 142 optAttribute("xml:lang", value); 143 return this; 144 } 145 146 public XmlStringBuilder escape(String text) { 147 assert text != null; 148 sb.append(StringUtils.escapeForXML(text)); 149 return this; 150 } 151 152 public XmlStringBuilder prelude(PacketExtension pe) { 153 halfOpenElement(pe.getElementName()); 154 xmlnsAttribute(pe.getNamespace()); 155 return this; 156 } 157 158 public XmlStringBuilder optAppend(CharSequence csq) { 159 if (csq != null) { 160 append(csq); 161 } 162 return this; 163 } 164 165 public XmlStringBuilder append(XmlStringBuilder xsb) { 166 assert xsb != null; 167 sb.append(xsb.sb); 168 return this; 169 } 170 171 public XmlStringBuilder emptyElement(String element) { 172 halfOpenElement(element); 173 return closeEmptyElement(); 174 } 175 176 public XmlStringBuilder condEmptyElement(boolean condition, String element) { 177 if (condition) { 178 emptyElement(element); 179 } 180 return this; 181 } 182 183 public XmlStringBuilder condAttribute(boolean condition, String name, String value) { 184 if (condition) { 185 attribute(name, value); 186 } 187 return this; 188 } 189 190 @Override 191 public XmlStringBuilder append(CharSequence csq) { 192 assert csq != null; 193 sb.append(csq); 194 return this; 195 } 196 197 @Override 198 public XmlStringBuilder append(CharSequence csq, int start, int end) { 199 assert csq != null; 200 sb.append(csq, start, end); 201 return this; 202 } 203 204 @Override 205 public XmlStringBuilder append(char c) { 206 sb.append(c); 207 return this; 208 } 209 210 @Override 211 public int length() { 212 return sb.length(); 213 } 214 215 @Override 216 public char charAt(int index) { 217 return sb.charAt(index); 218 } 219 220 @Override 221 public CharSequence subSequence(int start, int end) { 222 return sb.subSequence(start, end); 223 } 224 225 @Override 226 public String toString() { 227 return sb.toString(); 228 } 229 230 @Override 231 public boolean equals(Object other) { 232 if (!(other instanceof XmlStringBuilder)) { 233 return false; 234 } 235 XmlStringBuilder otherXmlStringBuilder = (XmlStringBuilder) other; 236 return toString().equals(otherXmlStringBuilder.toString()); 237 } 238 239 @Override 240 public int hashCode() { 241 return toString().hashCode(); 242 } 243}