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}