/**
 * $RCSfile$
 * $Revision$
 * $Date$
 *
 * Copyright 2003-2007 Jive Software.
 *
 * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jivesoftware.smackx.packet;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smack.util.StringUtils;

/**
 * A VCard class for use with the
 * <a href="http://www.jivesoftware.org/smack/" target="_blank">SMACK jabber library</a>.<p>
 * <p/>
 * You should refer to the
 * <a href="http://www.jabber.org/jeps/jep-0054.html" target="_blank">JEP-54 documentation</a>.<p>
 * <p/>
 * Please note that this class is incomplete but it does provide the most commonly found
 * information in vCards. Also remember that VCard transfer is not a standard, and the protocol
 * may change or be replaced.<p>
 * <p/>
 * <b>Usage:</b>
 * <pre>
 * <p/>
 * // To save VCard:
 * <p/>
 * VCard vCard = new VCard();
 * vCard.setFirstName("kir");
 * vCard.setLastName("max");
 * vCard.setEmailHome("foo@fee.bar");
 * vCard.setJabberId("jabber@id.org");
 * vCard.setOrganization("Jetbrains, s.r.o");
 * vCard.setNickName("KIR");
 * <p/>
 * vCard.setField("TITLE", "Mr");
 * vCard.setAddressFieldHome("STREET", "Some street");
 * vCard.setAddressFieldWork("CTRY", "US");
 * vCard.setPhoneWork("FAX", "3443233");
 * <p/>
 * vCard.save(connection);
 * <p/>
 * // To load VCard:
 * <p/>
 * VCard vCard = new VCard();
 * vCard.load(conn); // load own VCard
 * vCard.load(conn, "joe@foo.bar"); // load someone's VCard
 * </pre>
 *
 * @author Kirill Maximov (kir@maxkir.com)
 */
public class VCard extends IQ {

    /**
     * Phone types:
     * VOICE?, FAX?, PAGER?, MSG?, CELL?, VIDEO?, BBS?, MODEM?, ISDN?, PCS?, PREF?
     */
    private Map<String, String> homePhones = new HashMap<String, String>();
    private Map<String, String> workPhones = new HashMap<String, String>();


    /**
     * Address types:
     * POSTAL?, PARCEL?, (DOM | INTL)?, PREF?, POBOX?, EXTADR?, STREET?, LOCALITY?,
     * REGION?, PCODE?, CTRY?
     */
    private Map<String, String> homeAddr = new HashMap<String, String>();
    private Map<String, String> workAddr = new HashMap<String, String>();

    private String firstName;
    private String lastName;
    private String middleName;

    private String emailHome;
    private String emailWork;

    private String organization;
    private String organizationUnit;

    private String photoMimeType;
    private String photoBinval;

    /**
     * Such as DESC ROLE GEO etc.. see JEP-0054
     */
    private Map<String, String> otherSimpleFields = new HashMap<String, String>();

    // fields that, as they are should not be escaped before forwarding to the server
    private Map<String, String> otherUnescapableFields = new HashMap<String, String>();

    public VCard() {
    }

    /**
     * Set generic VCard field.
     *
     * @param field value of field. Possible values: NICKNAME, PHOTO, BDAY, JABBERID, MAILER, TZ,
     *              GEO, TITLE, ROLE, LOGO, NOTE, PRODID, REV, SORT-STRING, SOUND, UID, URL, DESC.
     */
    public String getField(String field) {
        return otherSimpleFields.get(field);
    }

    /**
     * Set generic VCard field.
     *
     * @param value value of field
     * @param field field to set. See {@link #getField(String)}
     * @see #getField(String)
     */
    public void setField(String field, String value) {
        setField(field, value, false);
    }

    /**
     * Set generic, unescapable VCard field. If unescabale is set to true, XML maybe a part of the
     * value.
     *
     * @param value         value of field
     * @param field         field to set. See {@link #getField(String)}
     * @param isUnescapable True if the value should not be escaped, and false if it should.
     */
    public void setField(String field, String value, boolean isUnescapable) {
        if (!isUnescapable) {
            otherSimpleFields.put(field, value);
        }
        else {
            otherUnescapableFields.put(field, value);
        }
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
        // Update FN field
        updateFN();
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
        // Update FN field
        updateFN();
    }

    public String getMiddleName() {
        return middleName;
    }

    public void setMiddleName(String middleName) {
        this.middleName = middleName;
        // Update FN field
        updateFN();
    }

    public String getNickName() {
        return otherSimpleFields.get("NICKNAME");
    }

    public void setNickName(String nickName) {
        otherSimpleFields.put("NICKNAME", nickName);
    }

    public String getEmailHome() {
        return emailHome;
    }

    public void setEmailHome(String email) {
        this.emailHome = email;
    }

    public String getEmailWork() {
        return emailWork;
    }

    public void setEmailWork(String emailWork) {
        this.emailWork = emailWork;
    }

    public String getJabberId() {
        return otherSimpleFields.get("JABBERID");
    }

    public void setJabberId(String jabberId) {
        otherSimpleFields.put("JABBERID", jabberId);
    }

    public String getOrganization() {
        return organization;
    }

    public void setOrganization(String organization) {
        this.organization = organization;
    }

    public String getOrganizationUnit() {
        return organizationUnit;
    }

    public void setOrganizationUnit(String organizationUnit) {
        this.organizationUnit = organizationUnit;
    }

    /**
     * Get home address field
     *
     * @param addrField one of POSTAL, PARCEL, (DOM | INTL), PREF, POBOX, EXTADR, STREET,
     *                  LOCALITY, REGION, PCODE, CTRY
     */
    public String getAddressFieldHome(String addrField) {
        return homeAddr.get(addrField);
    }

    /**
     * Set home address field
     *
     * @param addrField one of POSTAL, PARCEL, (DOM | INTL), PREF, POBOX, EXTADR, STREET,
     *                  LOCALITY, REGION, PCODE, CTRY
     */
    public void setAddressFieldHome(String addrField, String value) {
        homeAddr.put(addrField, value);
    }

    /**
     * Get work address field
     *
     * @param addrField one of POSTAL, PARCEL, (DOM | INTL), PREF, POBOX, EXTADR, STREET,
     *                  LOCALITY, REGION, PCODE, CTRY
     */
    public String getAddressFieldWork(String addrField) {
        return workAddr.get(addrField);
    }

    /**
     * Set work address field
     *
     * @param addrField one of POSTAL, PARCEL, (DOM | INTL), PREF, POBOX, EXTADR, STREET,
     *                  LOCALITY, REGION, PCODE, CTRY
     */
    public void setAddressFieldWork(String addrField, String value) {
        workAddr.put(addrField, value);
    }


    /**
     * Set home phone number
     *
     * @param phoneType one of VOICE, FAX, PAGER, MSG, CELL, VIDEO, BBS, MODEM, ISDN, PCS, PREF
     * @param phoneNum  phone number
     */
    public void setPhoneHome(String phoneType, String phoneNum) {
        homePhones.put(phoneType, phoneNum);
    }

    /**
     * Get home phone number
     *
     * @param phoneType one of VOICE, FAX, PAGER, MSG, CELL, VIDEO, BBS, MODEM, ISDN, PCS, PREF
     */
    public String getPhoneHome(String phoneType) {
        return homePhones.get(phoneType);
    }

    /**
     * Set work phone number
     *
     * @param phoneType one of VOICE, FAX, PAGER, MSG, CELL, VIDEO, BBS, MODEM, ISDN, PCS, PREF
     * @param phoneNum  phone number
     */
    public void setPhoneWork(String phoneType, String phoneNum) {
        workPhones.put(phoneType, phoneNum);
    }

    /**
     * Get work phone number
     *
     * @param phoneType one of VOICE, FAX, PAGER, MSG, CELL, VIDEO, BBS, MODEM, ISDN, PCS, PREF
     */
    public String getPhoneWork(String phoneType) {
        return workPhones.get(phoneType);
    }

    /**
     * Set the avatar for the VCard by specifying the url to the image.
     *
     * @param avatarURL the url to the image(png,jpeg,gif,bmp)
     */
    public void setAvatar(URL avatarURL) {
        byte[] bytes = new byte[0];
        try {
            bytes = getBytes(avatarURL);
        }
        catch (IOException e) {
            e.printStackTrace();
        }

        setAvatar(bytes);
    }

    /**
     * Removes the avatar from the vCard
     *
     *  This is done by setting the PHOTO value to the empty string as defined in XEP-0153
     */
    public void removeAvatar() {
        // Remove avatar (if any)
        photoBinval = null;
        photoMimeType = null;
    }

    /**
     * Specify the bytes of the JPEG for the avatar to use.
     * If bytes is null, then the avatar will be removed.
     * 'image/jpeg' will be used as MIME type.
     *
     * @param bytes the bytes of the avatar, or null to remove the avatar data
     */
    public void setAvatar(byte[] bytes) {
        setAvatar(bytes, "image/jpeg");
    }

    /**
     * Specify the bytes for the avatar to use as well as the mime type.
     *
     * @param bytes the bytes of the avatar.
     * @param mimeType the mime type of the avatar.
     */
    public void setAvatar(byte[] bytes, String mimeType) {
        // If bytes is null, remove the avatar
        if (bytes == null) {
            removeAvatar();
            return;
        }

        // Otherwise, add to mappings.
        String encodedImage = StringUtils.encodeBase64(bytes);

        setAvatar(encodedImage, mimeType);
    }

    /**
     * Specify the Avatar used for this vCard.
     *
     * @param encodedImage the Base64 encoded image as String
     * @param mimeType the MIME type of the image
     */
    public void setAvatar(String encodedImage, String mimeType) {
        photoBinval = encodedImage;
        photoMimeType = mimeType;
    }

    /**
     * Return the byte representation of the avatar(if one exists), otherwise returns null if
     * no avatar could be found.
     * <b>Example 1</b>
     * <pre>
     * // Load Avatar from VCard
     * byte[] avatarBytes = vCard.getAvatar();
     * <p/>
     * // To create an ImageIcon for Swing applications
     * ImageIcon icon = new ImageIcon(avatar);
     * <p/>
     * // To create just an image object from the bytes
     * ByteArrayInputStream bais = new ByteArrayInputStream(avatar);
     * try {
     *   Image image = ImageIO.read(bais);
     *  }
     *  catch (IOException e) {
     *    e.printStackTrace();
     * }
     * </pre>
     *
     * @return byte representation of avatar.
     */
    public byte[] getAvatar() {
        if (photoBinval == null) {
            return null;
        }
        return StringUtils.decodeBase64(photoBinval);
    }

    /**
     * Returns the MIME Type of the avatar or null if none is set
     *
     * @return the MIME Type of the avatar or null
     */
    public String getAvatarMimeType() {
        return photoMimeType;
    }

    /**
     * Common code for getting the bytes of a url.
     *
     * @param url the url to read.
     */
    public static byte[] getBytes(URL url) throws IOException {
        final String path = url.getPath();
        final File file = new File(path);
        if (file.exists()) {
            return getFileBytes(file);
        }

        return null;
    }

    private static byte[] getFileBytes(File file) throws IOException {
        BufferedInputStream bis = null;
        try {
            bis = new BufferedInputStream(new FileInputStream(file));
            int bytes = (int) file.length();
            byte[] buffer = new byte[bytes];
            int readBytes = bis.read(buffer);
            if (readBytes != buffer.length) {
                throw new IOException("Entire file not read");
            }
            return buffer;
        }
        finally {
            if (bis != null) {
                bis.close();
            }
        }
    }

    /**
     * Returns the SHA-1 Hash of the Avatar image.
     *
     * @return the SHA-1 Hash of the Avatar image.
     */
    public String getAvatarHash() {
        byte[] bytes = getAvatar();
        if (bytes == null) {
            return null;
        }

        MessageDigest digest;
        try {
            digest = MessageDigest.getInstance("SHA-1");
        }
        catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }

        digest.update(bytes);
        return StringUtils.encodeHex(digest.digest());
    }

    private void updateFN() {
        StringBuilder sb = new StringBuilder();
        if (firstName != null) {
            sb.append(StringUtils.escapeForXML(firstName)).append(' ');
        }
        if (middleName != null) {
            sb.append(StringUtils.escapeForXML(middleName)).append(' ');
        }
        if (lastName != null) {
            sb.append(StringUtils.escapeForXML(lastName));
        }
        setField("FN", sb.toString());
    }

    /**
     * Save this vCard for the user connected by 'connection'. Connection should be authenticated
     * and not anonymous.<p>
     * <p/>
     * NOTE: the method is asynchronous and does not wait for the returned value.
     *
     * @param connection the Connection to use.
     * @throws XMPPException thrown if there was an issue setting the VCard in the server.
     */
    public void save(Connection connection) throws XMPPException {
        checkAuthenticated(connection, true);

        setType(IQ.Type.SET);
        setFrom(connection.getUser());
        PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(getPacketID()));
        connection.sendPacket(this);

        Packet response = collector.nextResult(SmackConfiguration.getPacketReplyTimeout());

        // Cancel the collector.
        collector.cancel();
        if (response == null) {
            throw new XMPPException("No response from server on status set.");
        }
        if (response.getError() != null) {
            throw new XMPPException(response.getError());
        }
    }

    /**
     * Load VCard information for a connected user. Connection should be authenticated
     * and not anonymous.
     */
    public void load(Connection connection) throws XMPPException {
        checkAuthenticated(connection, true);

        setFrom(connection.getUser());
        doLoad(connection, connection.getUser());
    }

    /**
     * Load VCard information for a given user. Connection should be authenticated and not anonymous.
     */
    public void load(Connection connection, String user) throws XMPPException {
        checkAuthenticated(connection, false);

        setTo(user);
        doLoad(connection, user);
    }

    private void doLoad(Connection connection, String user) throws XMPPException {
        setType(Type.GET);
        PacketCollector collector = connection.createPacketCollector(
                new PacketIDFilter(getPacketID()));
        connection.sendPacket(this);

        VCard result = null;
        try {
            result = (VCard) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());

            if (result == null) {
                String errorMessage = "Timeout getting VCard information";
                throw new XMPPException(errorMessage, new XMPPError(
                        XMPPError.Condition.request_timeout, errorMessage));
            }
            if (result.getError() != null) {
                throw new XMPPException(result.getError());
            }
        }
        catch (ClassCastException e) {
            System.out.println("No VCard for " + user);
        }

        copyFieldsFrom(result);
    }

    public String getChildElementXML() {
        StringBuilder sb = new StringBuilder();
        new VCardWriter(sb).write();
        return sb.toString();
    }

    private void copyFieldsFrom(VCard from) {
        Field[] fields = VCard.class.getDeclaredFields();
        for (Field field : fields) {
            if (field.getDeclaringClass() == VCard.class &&
                    !Modifier.isFinal(field.getModifiers())) {
                try {
                    field.setAccessible(true);
                    field.set(this, field.get(from));
                }
                catch (IllegalAccessException e) {
                    throw new RuntimeException("This cannot happen:" + field, e);
                }
            }
        }
    }

    private void checkAuthenticated(Connection connection, boolean checkForAnonymous) {
        if (connection == null) {
            throw new IllegalArgumentException("No connection was provided");
        }
        if (!connection.isAuthenticated()) {
            throw new IllegalArgumentException("Connection is not authenticated");
        }
        if (checkForAnonymous && connection.isAnonymous()) {
            throw new IllegalArgumentException("Connection cannot be anonymous");
        }
    }

    private boolean hasContent() {
        //noinspection OverlyComplexBooleanExpression
        return hasNameField()
                || hasOrganizationFields()
                || emailHome != null
                || emailWork != null
                || otherSimpleFields.size() > 0
                || otherUnescapableFields.size() > 0
                || homeAddr.size() > 0
                || homePhones.size() > 0
                || workAddr.size() > 0
                || workPhones.size() > 0
                || photoBinval != null
                ;
    }

    private boolean hasNameField() {
        return firstName != null || lastName != null || middleName != null;
    }

    private boolean hasOrganizationFields() {
        return organization != null || organizationUnit != null;
    }

    // Used in tests:

    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        final VCard vCard = (VCard) o;

        if (emailHome != null ? !emailHome.equals(vCard.emailHome) : vCard.emailHome != null) {
            return false;
        }
        if (emailWork != null ? !emailWork.equals(vCard.emailWork) : vCard.emailWork != null) {
            return false;
        }
        if (firstName != null ? !firstName.equals(vCard.firstName) : vCard.firstName != null) {
            return false;
        }
        if (!homeAddr.equals(vCard.homeAddr)) {
            return false;
        }
        if (!homePhones.equals(vCard.homePhones)) {
            return false;
        }
        if (lastName != null ? !lastName.equals(vCard.lastName) : vCard.lastName != null) {
            return false;
        }
        if (middleName != null ? !middleName.equals(vCard.middleName) : vCard.middleName != null) {
            return false;
        }
        if (organization != null ?
                !organization.equals(vCard.organization) : vCard.organization != null) {
            return false;
        }
        if (organizationUnit != null ?
                !organizationUnit.equals(vCard.organizationUnit) : vCard.organizationUnit != null) {
            return false;
        }
        if (!otherSimpleFields.equals(vCard.otherSimpleFields)) {
            return false;
        }
        if (!workAddr.equals(vCard.workAddr)) {
            return false;
        }
        if (photoBinval != null ? !photoBinval.equals(vCard.photoBinval) : vCard.photoBinval != null) {
            return false;
        }

        return workPhones.equals(vCard.workPhones);
    }

    public int hashCode() {
        int result;
        result = homePhones.hashCode();
        result = 29 * result + workPhones.hashCode();
        result = 29 * result + homeAddr.hashCode();
        result = 29 * result + workAddr.hashCode();
        result = 29 * result + (firstName != null ? firstName.hashCode() : 0);
        result = 29 * result + (lastName != null ? lastName.hashCode() : 0);
        result = 29 * result + (middleName != null ? middleName.hashCode() : 0);
        result = 29 * result + (emailHome != null ? emailHome.hashCode() : 0);
        result = 29 * result + (emailWork != null ? emailWork.hashCode() : 0);
        result = 29 * result + (organization != null ? organization.hashCode() : 0);
        result = 29 * result + (organizationUnit != null ? organizationUnit.hashCode() : 0);
        result = 29 * result + otherSimpleFields.hashCode();
        result = 29 * result + (photoBinval != null ? photoBinval.hashCode() : 0);
        return result;
    }

    public String toString() {
        return getChildElementXML();
    }

    //==============================================================

    private class VCardWriter {

        private final StringBuilder sb;

        VCardWriter(StringBuilder sb) {
            this.sb = sb;
        }

        public void write() {
            appendTag("vCard", "xmlns", "vcard-temp", hasContent(), new ContentBuilder() {
                public void addTagContent() {
                    buildActualContent();
                }
            });
        }

        private void buildActualContent() {
            if (hasNameField()) {
                appendN();
            }

            appendOrganization();
            appendGenericFields();
            appendPhoto();

            appendEmail(emailWork, "WORK");
            appendEmail(emailHome, "HOME");

            appendPhones(workPhones, "WORK");
            appendPhones(homePhones, "HOME");

            appendAddress(workAddr, "WORK");
            appendAddress(homeAddr, "HOME");
        }

        private void appendPhoto() {
            if (photoBinval == null)
                return;

            appendTag("PHOTO", true, new ContentBuilder() {
                public void addTagContent() {
                    appendTag("BINVAL", photoBinval); // No need to escape photoBinval, as it's already Base64 encoded
                    appendTag("TYPE", StringUtils.escapeForXML(photoMimeType));
                }
            });
        }
        private void appendEmail(final String email, final String type) {
            if (email != null) {
                appendTag("EMAIL", true, new ContentBuilder() {
                    public void addTagContent() {
                        appendEmptyTag(type);
                        appendEmptyTag("INTERNET");
                        appendEmptyTag("PREF");
                        appendTag("USERID", StringUtils.escapeForXML(email));
                    }
                });
            }
        }

        private void appendPhones(Map<String, String> phones, final String code) {
            Iterator<Map.Entry<String, String>> it = phones.entrySet().iterator();
            while (it.hasNext()) {
                final Map.Entry<String,String> entry = it.next();
                appendTag("TEL", true, new ContentBuilder() {
                    public void addTagContent() {
                        appendEmptyTag(entry.getKey());
                        appendEmptyTag(code);
                        appendTag("NUMBER", StringUtils.escapeForXML(entry.getValue()));
                    }
                });
            }
        }

        private void appendAddress(final Map<String, String> addr, final String code) {
            if (addr.size() > 0) {
                appendTag("ADR", true, new ContentBuilder() {
                    public void addTagContent() {
                        appendEmptyTag(code);

                        Iterator<Map.Entry<String, String>> it = addr.entrySet().iterator();
                        while (it.hasNext()) {
                            final Entry<String, String> entry = it.next();
                            appendTag(entry.getKey(), StringUtils.escapeForXML(entry.getValue()));
                        }
                    }
                });
            }
        }

        private void appendEmptyTag(Object tag) {
            sb.append('<').append(tag).append("/>");
        }

        private void appendGenericFields() {
            Iterator<Map.Entry<String, String>> it = otherSimpleFields.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String, String> entry = it.next();
                appendTag(entry.getKey().toString(),
                        StringUtils.escapeForXML(entry.getValue()));
            }

            it = otherUnescapableFields.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String, String> entry = it.next();
                appendTag(entry.getKey().toString(),entry.getValue());
            }
        }

        private void appendOrganization() {
            if (hasOrganizationFields()) {
                appendTag("ORG", true, new ContentBuilder() {
                    public void addTagContent() {
                        appendTag("ORGNAME", StringUtils.escapeForXML(organization));
                        appendTag("ORGUNIT", StringUtils.escapeForXML(organizationUnit));
                    }
                });
            }
        }

        private void appendN() {
            appendTag("N", true, new ContentBuilder() {
                public void addTagContent() {
                    appendTag("FAMILY", StringUtils.escapeForXML(lastName));
                    appendTag("GIVEN", StringUtils.escapeForXML(firstName));
                    appendTag("MIDDLE", StringUtils.escapeForXML(middleName));
                }
            });
        }

        private void appendTag(String tag, String attr, String attrValue, boolean hasContent,
                ContentBuilder builder) {
            sb.append('<').append(tag);
            if (attr != null) {
                sb.append(' ').append(attr).append('=').append('\'').append(attrValue).append('\'');
            }

            if (hasContent) {
                sb.append('>');
                builder.addTagContent();
                sb.append("</").append(tag).append(">\n");
            }
            else {
                sb.append("/>\n");
            }
        }

        private void appendTag(String tag, boolean hasContent, ContentBuilder builder) {
            appendTag(tag, null, null, hasContent, builder);
        }

        private void appendTag(String tag, final String tagText) {
            if (tagText == null) return;
            final ContentBuilder contentBuilder = new ContentBuilder() {
                public void addTagContent() {
                    sb.append(tagText.trim());
                }
            };
            appendTag(tag, true, contentBuilder);
        }

    }

    //==============================================================

    private interface ContentBuilder {

        void addTagContent();
    }

    //==============================================================
}

