public final class Constants {

    private Constants() {

    }

    public static final String EVERNOTE_INTERNATIONAL = "Evernote International";
    public static final String EVERNOTE_YINXIANG = "印象笔记";
    public static final String EVERNOTE_SANDBOX = "Evernote Sandbox";

    // Command IDs
    public static final String PLUGIN_COMMAND_PARAM_ID = "org.lttpp.eemory.command.parameter";
    public static final String PLUGIN_COMMAND_ID_CLIP_TO_EVERNOTE = "org.lttpp.eemory.commands.ClipToEvernote";
    public static final String PLUGIN_COMMAND_ID_CLIP_SELECTION_TO_EVERNOTE = "org.lttpp.eemory.commands.ClipSelectionToEvernote";
    public static final String PLUGIN_COMMAND_ID_CLIP_FILE_TO_EVERNOTE = "org.lttpp.eemory.commands.ClipFileToEvernote";
    public static final String PLUGIN_COMMAND_ID_CLIP_SCREENSHOT_TO_EVERNOTE = "org.lttpp.eemory.commands.ClipScreenshotToEvernote";
    public static final String PLUGIN_COMMAND_ID_CONFIGURATIONS = "org.lttpp.eemory.commands.Configurations";
    public static final String PLUGIN_TESTERS_ISFILE = "isFile";

    // field properties
    public static final String PLUGIN_CONFIGS_NOTEBOOK = "Plugin.Configurations.Notebook";
    public static final String PLUGIN_CONFIGS_NOTE = "Plugin.Configurations.Note";
    public static final String PLUGIN_CONFIGS_TAGS = "Plugin.Configurations.Tags";
    public static final String PLUGIN_CONFIGS_COMMENTS = "Plugin.Configurations.Comments";

    // Settings Keys
    public static final String PLUGIN_SETTINGS_KEY_TOKEN = "token";
    public static final String PLUGIN_SETTINGS_SECTION_NOTEBOOK = "notebook";
    public static final String PLUGIN_SETTINGS_SECTION_NOTE = "note";
    public static final String PLUGIN_SETTINGS_SECTION_TAGS = "tags";
    public static final String PLUGIN_SETTINGS_SECTION_COMMENTS = "comments";
    public static final String PLUGIN_SETTINGS_KEY_NAME = "name";
    public static final String PLUGIN_SETTINGS_KEY_GUID = "guid";
    public static final String PLUGIN_SETTINGS_KEY_TYPE = "type";
    public static final String PLUGIN_SETTINGS_KEY_OBJECT = "object";
    public static final String PLUGIN_SETTINGS_KEY_CHECKED = "isChecked";
    public static final String PLUGIN_SETTINGS_KEY_UUID = "uuid";
    public static final String PLUGIN_SETTINGS_KEY_BRAND = "brand";

    // Data Model
    public static final String ENML_MODEL_NOTE_NOTEGUID = "Note.guid";
    public static final String ENML_MODEL_NOTE_NOTEBOOKGUID = "Note.notebookGuid";
    public static final String ENML_MODEL_NOTEBOOKGUID = "Notebook.guid";
    public static final int PLUGIN_CONFIGS_REFRESH_ID = -143259786; // random number

    // DOM
    public static String XML = "xml";
    public static String VERSION = "version";
    public static String ENCODING = "encoding";
    public static String STANDALONE = "standalone";
    public static final String DOM_FRAGMENT_NAME = "#document-fragment";
    public static String NO = "no";

    // ENML
    public static final String XHTML_1_0_LATIN_1_ENT = "xhtml-lat1.ent";
    public static final String XHTML_1_0_SYMBOL_ENT = "xhtml-symbol.ent";
    public static final String XHTML_1_0_SPECIAL_ENT = "xhtml-special.ent";
    public static final String XML_VERSION_1_0 = "1.0";

    public static final String XHTML_1_0_LATIN_1_ENT_LOCATION = "dtd/xhtml-lat1.ent";
    public static final String XHTML_1_0_SYMBOL_ENT_LOCATION = "dtd/xhtml-symbol.ent";
    public static final String XHTML_1_0_SPECIAL_ENT_LOCATION = "dtd/xhtml-special.ent";

    public static final String ENML_DOCTYPE_DECLARATION_SYSTEM_ID = "http://xml.evernote.com/pub/enml2.dtd";
    public static final String ENML_DTD = "enml2.dtd";
    public static final String ENML_DTD_LOCATION = "dtd/enml2.dtd";

    public static final String ENML_VALUE_PT = "pt";
    public static final String ENML_VALUE_FONT_SIZE = "font-size:";
    public static final String ENML_ATTR_STYLE = "style";
    public static final String ENML_TAG_BR = "br";
    public static final String ENML_TAG_SPAN = "span";
    public static final String ENML_ATTR_HASH = "hash";
    public static final String ENML_ATTR_TYPE = "type";
    public static final String ENML_TAG_EN_MEDIA = "en-media";
    public static final String ENML_TAG_EN_NOTE = "en-note";
    public static final String ENML_TAG_DIV = "div";
    public static final String ENML_ATTR_SIZE = "size";
    public static final String ENML_ATTR_COLOR = "color";
    public static final String ENML_ATTR_FACE = "face";
    public static final String ENML_ATTR_FONT = "font";
    public static final String ENML_TAG_ITALIC = "i";
    public static final String ENML_TAG_BOLD = "b";
    public static final String DOM_NODE_NAME_TEXT = "#text";
    public static final String ENML_DOCTYPE_PUBLIC = "PUBLIC";
    public static final String ENML_DOCTYPE_SYSTEM = "SYSTEM";
    public static final String ENML_DOCTYPE = "DOCTYPE";
    /*
     * Regex: assume > does not appear in the value for the attributes, and the
     * XML is valid.
     */
    public static final String ENML_TAG_EN_NOTE_SELF_CLOSING_REGEX = "(<"+ENML_TAG_EN_NOTE+"[^>]*)/>";
    public static final String ENML_TAG_EN_NOTE_SELF_CLOSING_REPLACEMENT = "$1></" + ENML_TAG_EN_NOTE + ">";
    public static final String ENML_TAG_EN_NOTE_START_REGEX = "(<" + ENML_TAG_EN_NOTE + "[^>]*>)";
    public static final String ENML_TAG_EN_NOTE_START_REPLACEMENT_P1 = "$1";

    public static final String FONT_STYLE_NORMAL = "normal";
    public static final String FONT_STYLE_BOLD = "bold";
    public static final String FONT_STYLE_ITALIC = "italic";
    public static final String FONT_STYLE_BOLD_ITALIC = "bold-italic";
    public static final String HTML_NBSP = "&nbsp;";

    public static final String EDAM_SYNTAX_INTITLE = "intitle:";
    /* end */

    // OAuth
    public static final String JETTY_LOG_IMPL_CLASS = "org.eclipse.jetty.util.log.class";
    public static final String CALLBACK_URL = "/oauth/callback";
    public static final String OAUTH_VERIFIER = "oauth_verifier";
    public static final String CALLBACK_HTML_META = "text/html;charset=utf-8";
    public static final String OAUTH_EVERNOTE_TRADEMARK = "icons/evernote_32x32.png";
    public static final String OAUTH_EVERNOTE_TRADEMARK_DISCONNECTED = "icons/evernote_32x32.png";
    public static final String OAUTH_CALLBACK_HTML = "html/callback.html";
    public static final String OAUTH_CALLBACK_ERR_HTML = "html/callback_err.html";
    public static final String OAUTH_NOTTARGET_HTML = "html/images/default.html";
    public static final String OAUTH_RESOURCE_BASE = "html/images";
    public static final String OAUTH_DEFAULT_HTML = "default.html";

    // Store type
    public static final String ENOBJECT_TYPE_NORMAL = "normal";
    public static final String ENOBJECT_TYPE_LINKED = "linked";
    public static final String ENOBJECT_TYPE_BUSINESS = "business";

    // mime-util
    public static final String MimeDetector = "eu.medsea.mimeutil.detector.MagicMimeMimeDetector";

    // Plug-in
    public static final String PLUGIN_DEBUG_MODE = "org.lttpp.eemory.debug";
    public static final String PLUGIN_RUN_ON_SANDBOX = "com.evernote.sandbox";

    // Button properties
    public static final String Plugin_OAuth_AuthExpired_ReAuth = "Plugin_OAuth_AuthExpired_ReAuth";
    public static final String Plugin_OAuth_NotNow = "Plugin_OAuth_NotNow";
    public static final String Plugin_OAuth_Copy = "Plugin_OAuth_Copy";
    public static final String Plugin_OAuth_Cancel = "Plugin_OAuth_Cancel";

    // Others
    public static final String FileNamePartSimpleDateFormat = "yyyy-MM-dd'T'HH-mm-ss-";
    public static final String TAGS_SEPARATOR = ConstantsUtil.COMMA;
    public static final int TAB_WIDTH = 4;
    public static final String returnCode = "returnCode";
    public static final String toggleState = "toggleState";

} public class Messages extends NLS {

    private static final String BUNDLE_NAME = "messages"; //$NON-NLS-1$

    public static String Plugin_Configs_Shell_Title;
    public static String Plugin_Configs_QuickOrgnize_Shell_Title;
    public static String Plugin_Configs_Title;
    public static String Plugin_Configs_Message;
    public static String Plugin_Configs_Organize;
    public static String Plugin_Configs_Notebook;
    public static String Plugin_Configs_Note;
    public static String Plugin_Configs_Tags;
    public static String Plugin_Configs_Notebook_Hint;
    public static String Plugin_Configs_Note_Hint;
    public static String Plugin_Configs_Tags_Hint;
    public static String Plugin_Configs_Comments;
    public static String Plugin_Configs_Refresh;
    public static String Plugin_Configs_Authenticating;
    public static String Plugin_Configs_FetchingNotebooks;
    public static String Plugin_Configs_FetchingNotes;
    public static String Plugin_Configs_FetchingTags;
    public static String Plugin_Runtime_ClipFileToEvernote;
    public static String Plugin_Runtime_ClipSelectionToEvernote;
    public static String Plugin_Runtime_ClipScreenshotToEvernote_Hint;
    public static String Plugin_Runtime_CreateNewNote;
    public static String Plugin_Runtime_CreateNewNoteInNotebook;
    public static String Plugin_Runtime_ClipToDefault;
    public static String Plugin_Runtime_CreateNewNoteWithGivenName;
    public static String Plugin_Runtime_CreateNewNoteWithGivenNameInNotebook;
    public static String Plugin_Runtime_ClipToNotebook_Default;
    public static String Plugin_OutOfDate;
    public static String Plugin_Error_Occurred;
    public static String Plugin_Error_OutOfDate;
    public static String Plugin_Error_NoFile;
    public static String Plugin_Error_NoText;
    public static String Plugin_OAuth_Cancel;
    public static String Plugin_OAuth_Copy;

    public static String Plugin_OAuth_TokenNotConfigured;
    public static String Plugin_OAuth_Title;
    public static String Plugin_OAuth_Configure;
    public static String Plugin_OAuth_NotNow;
    public static String Plugin_OAuth_Waiting;
    public static String Plugin_OAuth_Confirm;
    public static String Plugin_OAuth_AuthExpired_Message;
    public static String Plugin_OAuth_AuthExpired_Title;
    public static String Plugin_OAuth_AuthExpired_ReAuth;
    public static String Plugin_OAuth_DoItManually;
    public static String Plugin_OAuth_SWITCH_YXBJ;
    public static String Plugin_OAuth_SWITCH_INTL;

    public static String DOM_Error0;
    public static String DOM_Error1;
    public static String DOM_Error2;
    public static String DOM_Error3;
    public static String DOM_Error4;
    public static String DOM_Error5;
    public static String DOM_Error6;
    public static String DOM_Error7;
    public static String DOM_Error8;
    public static String DOM_Error9;
    public static String Throwable_IllegalArgumentException_Message;
    public static String Throwable_NotSerializable_Message;

    // For Debug
    public static String Plugin_Debug_Default_Font_Style;
    public static String Plugin_Debug_StyleRange_Font_Style;
    public static String Plugin_Debug_FinalConcluded_Font_Style;
    public static String Plugin_Debug_NewClipper;
    public static String Plugin_Debug_IsFullScreenSupported;
    public static String Plugin_Debug_CapturedScreenshot;
    public static String Plugin_Debug_NoScreenCaptureProcessor;

    static {
        // initialize resource bundle
        NLS.initializeMessages(BUNDLE_NAME, Messages.class);
    }

    private Messages() {
    }

} public interface Attribute extends Node {

	/**
	 * Returns the name of this attribute.
	 *
	 * @return the name of this attribute
	 */
	public String getName();

	/**
	 * Returns the value of this attribute.
	 * 
	 * @return the value of this attribute
	 */
	public String getValue();

	/**
	 * Set the value of this attribute.
	 * 
	 * @param newValue
	 *            the value to set
	 */
	public void setValue(String newValue);

	/**
	 * The Element node this attribute is attached to or null if this attribute
	 * is not in use.
	 * 
	 * @return The Element node or null
	 */
	public Element getOwnerElement();

} public interface Document extends Node {

    /**
     * This is a convenience attribute that allows direct access to the child
     * node that is the document element of the document.
     * 
     * @return
     */
    public Element getDocumentElement();

    /**
     * Creates an element of the type specified. Note that the instance returned
     * implements the Element interface, so attributes can be specified directly
     * on the returned object. In addition, if there are known attributes with
     * default values, {@code Attribute} nodes representing them are
     * automatically created and attached to the element.
     * 
     * @param tagName
     *            The name of the element type to instantiate. For XML, this is
     *            case-sensitive, otherwise it depends on the case-sensitivity
     *            of the markup language in use. In that case, the name is
     *            mapped to the canonical form of that markup by the DOM
     *            implementation.
     * @return A new Element object with the nodeName attribute set to tagName
     */
    public Element createElement(String tagName);

    /**
     * Creates an empty DocumentFragment object.
     * 
     * @return A new DocumentFragment.
     */
    public DocumentFragment createDocumentFragment();

    /**
     * Creates a Text node given the specified string.
     * 
     * @param data
     *            The data for the node
     * @return The new Text object
     */
    public Text createTextNode(String data);

    /**
     * Creates an {@code Attribute} of the given name. Note that the
     * {@code Attribute} instance can then be set on an Element using the
     * setAttributeNode method.
     * 
     * @param name
     *            The name of the attribute
     * @return A new {@code Attribute} object with the nodeName attribute set to
     *         name. The value of the attribute is the empty string.
     */
    public Attribute createAttribute(String name);

    /**
     * Create an document type declaration with given name, public ID, system
     * ID.
     * 
     * @param name
     *            name of the document type
     * @param publicId
     *            public ID of the document type
     * @param systemId
     *            system ID of the document type
     * @return the created document type declaration
     */
    public DocumentType createDocumentType(final String name, final String publicId, final String systemId);

    /**
     * Returns a list of all the Elements in document order with a given tag
     * name and are contained in the document.
     * 
     * @param tagName
     *            The name of the tag to match on. The special value "*" matches
     *            all tags. For XML, the {@code tagName} parameter is
     *            case-sensitive, otherwise it depends on the case-sensitivity
     *            of the markup language in use.
     * @return A new list containing all the matched Elements.
     */
    public List<Node> getElementsByTagName(String tagName);

    /**
     * An attribute specifying the encoding used for this document at the time
     * of the parsing. This is null when it is not known, such as when the
     * Document was created in memory.
     * 
     * @return the encoding used for pasring
     */
    public String getInputEncoding();

    /**
     * An attribute specifying, as part of the XML declaration, the encoding of
     * this document. This is null when unspecified or when it is not known,
     * such as when the Document was created in memory.
     * 
     * @return the encoding of this document
     */
    public String getXmlEncoding();

    /**
     * Set the attribute specifying, as part of the XML declaration, the
     * encoding of this document.
     * 
     * @param encoding
     *            XML encoding as part of declaration
     */
    public void setXMLEncoding(String encoding);

    /**
     * An attribute specifying, as part of the XML declaration, whether this
     * document is standalone. This is false when unspecified.
     * 
     * @return true if XML is standalone, false otherwise
     */
    public boolean getXmlStandalone();

    /**
     * An attribute specifying, as part of the XML declaration, whether this
     * document is standalone. This is false when unspecified.
     * 
     * @param standalone
     *            document standalone value to set
     */
    public void setXmlStandalone(boolean standalone);

    /**
     * An attribute specifying, as part of the XML declaration, the version
     * number of this document. If there is no declaration and if this document
     * supports the "XML" feature, the value is "1.0". If this document does not
     * support the "XML" feature, the value is always null.
     * 
     * @return XML version
     */
    public String getXmlVersion();

    /**
     * Set the attribute specifying, as part of the XML declaration, the version
     * number of this document. If there is no declaration and if this document
     * supports the "XML" feature, the value is "1.0". If this document does not
     * support the "XML" feature, the value is always null.
     * 
     * @param xmlVersion
     *            XML version to set
     */
    public void setXmlVersion(String xmlVersion);

    /**
     * An attribute specifying whether error checking is enforced or not. When
     * set to false, the implementation is free to not test every possible error
     * case normally defined on DOM operations, and not raise any DOMException
     * on DOM operations or report errors while using
     * Document.normalizeDocument(). In case of error, the behavior is
     * undefined. This attribute is true by default.
     * 
     * @return true if strict error checking, false otherwise
     */
    public boolean getStrictErrorChecking();

    /**
     * An attribute specifying whether error checking is enforced or not. When
     * set to false, the implementation is free to not test every possible error
     * case normally defined on DOM operations, and not raise any DOMException
     * on DOM operations or report errors while using
     * Document.normalizeDocument(). In case of error, the behavior is
     * undefined. This attribute is true by default.
     * 
     * @param strictErrorChecking
     *            error checking to set
     */
    public void setStrictErrorChecking(boolean strictErrorChecking);

    /**
     * Imports a node from another document to this document, without altering
     * or removing the source node from the original document; this method
     * creates a new copy of the source node. The returned node has no parent;
     * (parentNode is null). For all nodes, importing a node creates a node
     * object owned by the importing document, with attribute values identical
     * to the source node's nodeName and nodeType.
     * 
     * @param sourceNode
     *            The node to import
     * @param deep
     *            If true, recursively import the subtree under the specified
     *            node; if false, import only the node itself, as explained
     *            above. This has no effect on nodes that cannot have any
     *            children, and on {@code Attribute}, and EntityReference nodes.
     * @return The imported node that belongs to this Document.
     * @throws DOMException
     *             NOT_SUPPORTED_ERR: Raised if the type of node being imported
     *             is not supported.
     */
    public Node importNode(Node sourceNode, boolean deep) throws DOMException;

    /**
     * Attempts to adopt a node from another document to this document. If
     * supported, it changes the ownerDocument of the source node, its children,
     * as well as the attached attribute nodes if there are any. If the source
     * node has a parent it is first removed from the child list of its parent.
     * This effectively allows moving a subtree from one document to another
     * (unlike importNode() which create a copy of the source node instead of
     * moving it). When it fails, applications should use Document.importNode()
     * instead. Note that if the adopted node is already part of this document
     * (i.e. the source and target document are the same), this method still has
     * the effect of removing the source node from the child list of its parent,
     * if any.
     * 
     * @param sourceNode
     *            The node to move into this document
     * @return The adopted node, or null if this operation fails, such as when
     *         the source node comes from a different implementation.
     * @throws DOMException
     *             NOT_SUPPORTED_ERR: Raised if the source node is of type
     *             DOCUMENT, DOCUMENT_TYPE.
     */
    public Node adoptNode(Node sourceNode) throws DOMException;

    /**
     * This method acts as if the document was going through a save and load
     * cycle, putting the document in a "normal" form. As a consequence, this
     * method normalizes {@code Text} nodes, as defined in the method
     * {@code Node.normalize()}.
     */
    public void normalizeDocument();
} public interface DocumentFragment extends Node {

	/**
	 * Insert a fragment at the start. null to be "null".
	 *
	 * @param fragment
	 *            The document fragment to insert.
	 */
	public void insertFragment(DocumentFragment fragment);

	/**
	 * Append a fragment to the end. null to be "null".
	 *
	 * @param fragment
	 *            The document fragment to append.
	 */
	public void appendFragment(DocumentFragment fragment);

} public abstract interface DocumentType extends Node {

    public abstract String getName();

    public abstract String getPublicId();

    public abstract String getSystemId();

} public interface Node {

    public static final short NODE = 0;
    public static final short ELEMENT_NODE = 1;
    public static final short ATTRIBUTE_NODE = 2;
    public static final short TEXT_NODE = 3;
    public static final short DOCUMENT_NODE = 4;
    public static final short DOCUMENT_TYPE_NODE = 5;
    public static final short DOCUMENT_FRAGMENT_NODE = 6;

    /**
     * The name of this node, depending on its type.
     *
     * @return The name of this node
     */
    public String getNodeName();

    /**
     * Get the value of this node, depending on its type.
     *
     * @return The value of this node
     */
    public String getNodeValue();

    /**
     * Set the value of this node, depending on its type.
     *
     * @param newValue
     *            The value to be set
     */
    public void setNodeValue(String newValue);

    /**
     * A code representing the type of the underlying object.
     *
     * @return A code of type
     */
    public short getNodeType();

    /**
     * The parent of this node. All nodes, except {@code Attribute}, Document,
     * DocumentFragment, may have a parent. However, if a node has just been
     * created and not yet added to the tree, or if it has been removed from the
     * tree, this is null.
     *
     * @return The parent of this node
     */
    public Node getParentNode();

    /**
     * A list of node that contains all children of this node. If there are no
     * children, this is an empty list containing no nodes.
     *
     * @return A list of node that contains all children of this node
     */
    public List<Node> getChildNodes();

    /**
     * The first child of this node. If there is no such node, this returns
     * null.
     *
     * @return The first node, or null
     */
    public Node getFirstChild();

    /**
     * The last child of this node. If there is no such node, this returns null.
     *
     * @return The last node, or null
     */
    public Node getLastChild();

    /**
     * The node immediately preceding this node. If there is no such node, this
     * returns null.
     *
     * @return The node preceding this node, or null
     */
    public Node getPreviousSibling();

    /**
     * The node immediately following this node. If there is no such node, this
     * returns null.
     *
     * @return The node following this node, or null
     */
    public Node getNextSibling();

    /**
     * A map containing the attributes of this node (if it is an Element) or
     * null otherwise.
     *
     * @return A map containing the attributes
     */
    public abstract Map<String, Node> getAttributes();

    /**
     * The Document object associated with this node. This is also the Document
     * object used to create new nodes. When this node is a Document or a
     * DocumentType which is not used with any Document yet, this is null.
     *
     * @return The Document, or null
     */
    public Document getOwnerDocument();

    /**
     * Inserts the node newChild before the existing child node refChild. If
     * refChild is null, insert newChild at the end of the list of children.If
     * the newChild is already in the tree, it is first removed.
     *
     * @param newChild
     *            The node to insert
     * @param refChild
     *            The reference node, i.e., the node before which the new node
     *            must be inserted.
     * @return The node being inserted
     * @throws DOMException
     *             <p>
     *             HIERARCHY_REQUEST_ERR: Raised if this node is of a type that
     *             does not allow children of the type of the newChild node, or
     *             if the node to insert is one of this node's ancestors or this
     *             node itself, or if this node is of type Document and the DOM
     *             application attempts to insert a second DocumentType or
     *             Element node.
     *             </p>
     *             <p>
     *             WRONG_DOCUMENT_ERR: Raised if newChild was created from a
     *             different document than the one that created this node.
     *             </p>
     *             <p>
     *             NOT_FOUND_ERR: Raised if {@code refChild} is not a child of
     *             this node.
     *             </p>
     */
    public Node insertBefore(Node newChild, Node refChild) throws DOMException;

    /**
     * Replaces the child node oldChild with newChild in the list of children,
     * and returns the oldChild node. If the newChild is already in the tree, it
     * is first removed.
     *
     * @param newChild
     *            The new node to put in the child list
     * @param oldChild
     *            The node being replaced in the list
     * @return The node replaced
     * @throws DOMException
     *             <p>
     *             HIERARCHY_REQUEST_ERR: Raised if this node is of a type that
     *             does not allow children of the type of the newChild node, or
     *             if the node to put in is one of this node's ancestors or this
     *             node itself, or if this node is of type Document and the
     *             result of the replacement operation would add a second
     *             DocumentType or Element on the Document node.
     *             </p>
     *             <p>
     *             WRONG_DOCUMENT_ERR: Raised if newChild was created from a
     *             different document than the one that created this node.
     *             </p>
     *             <p>
     *             NOT_FOUND_ERR: Raised if oldChild is not a child of this
     *             node.
     *             </p>
     */
    public Node replaceChild(Node newChild, Node oldChild) throws DOMException;

    /**
     * Removes the child node indicated by oldChild from the list of children,
     * and returns it.
     *
     * @param oldChild
     *            The node being removed
     * @return The node removed
     * @throws DOMException
     *             <p>
     *             NOT_FOUND_ERR: Raised if oldChild is not a child of this
     *             node.
     *             </p>
     */
    public Node removeChild(Node oldChild) throws DOMException;

    /**
     * Adds the node newChild to the end of the list of children of this node.
     * If the newChild is already in the tree, it is first removed.
     *
     * @param newChild
     *            The node to add.If it is a {@code DocumentFragment} object,
     *            the entire contents of the document fragment are moved into
     *            the child list of this node
     * @return The node added
     * @throws DOMException
     *             <p>
     *             HIERARCHY_REQUEST_ERR: Raised if this node is of a type that
     *             does not allow children of the type of the newChild node, or
     *             if the node to append is one of this node's ancestors or this
     *             node itself, or if this node is of type Document and the DOM
     *             application attempts to append a second DocumentType or
     *             Element node.
     *             </p>
     *             <p>
     *             WRONG_DOCUMENT_ERR: Raised if newChild was created from a
     *             different document than the one that created this node.
     *             </p>
     */
    public Node appendChild(Node newChild) throws DOMException;

    /**
     * Returns whether this node has any children.
     *
     * @return true if this node has any children, false otherwise
     */
    public boolean hasChildNodes();

    /**
     * Returns a clone of this node, i.e., serves as a generic copy constructor
     * for nodes. The duplicate node has no parent ( parentNode is null).
     * Cloning an Element copies all attributes and their values, but this
     * method does not copy any children it contains unless it is a deep clone.
     * This includes text contained in the Element since the text is contained
     * in a child Text node. Cloning an {@code Attribute} directly, as opposed
     * to be cloned as part of an Element cloning operation, returns a specified
     * attribute (specified is true). Cloning an {@code Attribute} always clones
     * its children, since they represent its value, no matter whether this is a
     * deep clone or not. Cloning any other type of node simply returns a copy
     * of this node. In addition, cloning Document, DocumentType is
     * implementation dependent.
     * 
     * @param deep
     *            If true, recursively clone the subtree under the specified
     *            node; if false, clone only the node itself (and its
     *            attributes, if it is an Element).
     * @return The cloned node
     */
    public Node cloneNode(boolean deep);

    /**
     * Puts all Text nodes in the full depth of the sub-tree underneath this
     * Node, including attribute nodes, into a "normal" form where only
     * structure separates Text nodes, i.e., there are neither adjacent Text
     * nodes nor empty Text nodes. This can be used to ensure that the DOM view
     * of a document is the same as if it were saved and re-loaded, and is
     * useful when operations that depend on a particular document tree
     * structure are to be used.
     */
    public void normalize();

    /**
     * Returns whether this node (if it is an element) has any attributes.
     *
     * @return true if this node has any attributes, false otherwise
     */
    public boolean hasAttributes();

    /**
     * This attribute returns the text content of this node and its descendants.
     * When it is defined to be null, setting it has no effect. On setting, any
     * possible children this node may have are removed and, if it the new
     * string is not empty or null, replaced by a single Text node containing
     * the string this attribute is set to. On getting, no serialization is
     * performed, the returned string does not contain any markup. No whitespace
     * normalization is performed and the returned string does not contain the
     * white spaces in element content (see the attribute
     * Text.isElementContentWhitespace). Similarly, on setting, no parsing is
     * performed either, the input string is taken as pure textual content. The
     * string returned is made of the text content of this node depending on its
     * type, as defined below:
     *
     * <pre>
     * <table>
     * <tr>
     * <td>Node type</td>
     * <td>Content</td>
     * </tr>
     * <tr>
     * <td>ELEMENT_NODE, ATTRIBUTE_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
     * DOCUMENT_FRAGMENT_NODE</td>
     * <td>concatenation of the textContent attribute value of every child node,
     * excluding COMMENT_NODE and PROCESSING_INSTRUCTION_NODE nodes. This is the
     * empty string if the node has no children.</td>
     * </tr>
     * <tr>
     * <td>TEXT_NODE, CDATA_SECTION_NODE, COMMENT_NODE,
     * PROCESSING_INSTRUCTION_NODE</td>
     * <td>nodeValue</td>
     * </tr>
     * <td>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
     * <td>null</td>
     * </table>
     * </pre>
     *
     * @return the text content
     */
    public String getTextContent();

    /**
     * This attribute returns the text content of this node and its descendants.
     * When it is defined to be null, setting it has no effect. On setting, any
     * possible children this node may have are removed and, if it the new
     * string is not empty or null, replaced by a single Text node containing
     * the string this attribute is set to. On getting, no serialization is
     * performed, the returned string does not contain any markup. No whitespace
     * normalization is performed and the returned string does not contain the
     * white spaces in element content (see the attribute
     * Text.isElementContentWhitespace). Similarly, on setting, no parsing is
     * performed either, the input string is taken as pure textual content. The
     * string returned is made of the text content of this node depending on its
     * type, as defined below:
     *
     * <pre>
     * <table>
     * <tr>
     * <td>Node type</td>
     * <td>Content</td>
     * </tr>
     * <tr>
     * <td>ELEMENT_NODE, ATTRIBUTE_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
     * DOCUMENT_FRAGMENT_NODE</td>
     * <td>concatenation of the textContent attribute value of every child node,
     * excluding COMMENT_NODE and PROCESSING_INSTRUCTION_NODE nodes. This is the
     * empty string if the node has no children.</td>
     * </tr>
     * <tr>
     * <td>TEXT_NODE, CDATA_SECTION_NODE, COMMENT_NODE,
     * PROCESSING_INSTRUCTION_NODE</td>
     * <td>nodeValue</td>
     * </tr>
     * <td>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
     * <td>null</td>
     * </table>
     * </pre>
     *
     * @param text
     */
    public void setTextContent(String text);

    /**
     * Returns whether this node is the same node as the given one. This method
     * provides a way to determine whether two Node references returned by the
     * implementation reference the same object. When two Node references are
     * references to the same object, even if through a proxy, the references
     * may be used completely interchangeably, such that all attributes have the
     * same values and calling the same DOM method on either reference always
     * has exactly the same effect.
     *
     * @param other
     *            The node to test against
     * @return true if the nodes are the same, false otherwise
     */
    public boolean isSameNode(Node other);

	                                                                                        /**
     * Tests whether two nodes are equal. This method tests for equality of
     * nodes, not sameness (i.e., whether the two nodes are references to the
     * same object) which can be tested with {@code Node.isSameNode()}. All
     * nodes that are the same will also be equal, though the reverse may not be
     * true. Two nodes are equal if and only if the following conditions are
     * satisfied:
     * <ul>
     * <li>
     * The two nodes are of the same type.
     * <li>
     * The following string attributes are equal: {@code nodeName},
     * {@code nodeValue}. This is: they are both null, or they have the same
     * length and are character for character identical.</li>
     * <li>The attributes are equal. This is: they are both null, or they have
     * the same length and for each node that exists in one map there is a node
     * that exists in the other map and is equal, although not necessarily at
     * the same index.</li>
     * <li>The child nodes are equal. This is: they are both null, or they have
     * the same length and contain equal nodes at the same index. Note that
     * normalization can affect equality; to avoid this, nodes should be
     * normalized before being compared.</li>
     * </ul>
     * 
     * For two {@code DocumentType} nodes to be equal, the following conditions
     * must also be satisfied:
     * <ul>
     * <li>The following string attributes are equal: {@code publicId},
     * {@code systemId}, internalSubset.</li>
     * </ul>
     * 
     * On the other hand, the following do not affect equality: the
     * {@code ownerDocument} and {@code parentNode} attributes, the specified
     * attribute for {@code Attribute} nodes and Element nodes.
     * 
     * <p>
     * <b>Note</b>: As a general rule, anything not mentioned in the description
     * above is not significant in consideration of equality checking. Note that
     * future versions of this specification may take into account more
     * attributes and implementations conform to this specification are expected
     * to be updated accordingly.
     * </p>
     * 
     * @param other
     *            The node to compare equality with.
     * @return true if the nodes are equal, false otherwise.
     */
    public boolean isEqualNode(Node other);

} public interface Text extends Node {

    /**
     * The length of text, may be zero.
     *
     * @return The length of text
     */
    public int getLength();

    /**
     * Append the string to the end of the character data of the node. Upon
     * success, data provides access to the concatenation of data and the
     * DOMString specified.
     *
     * @param text
     *            The DOMString to append.
     */
    public void appendText(String text);

    /**
     * Insert a string at the specified 16-bit unit offset.
     *
     * @param offset
     *            The character offset at which to insert.
     * @param text
     *            The DOMString to insert.
     * @throws DOMException
     *             INDEX_SIZE_ERR: Raised if the specified offset is negative or
     *             greater than the length of data.
     */
    public void insertText(int offset, String text) throws DOMException;

    /**
     * Remove a range of 16-bit units from the node. Upon success, data and
     * length reflect the change.
     *
     * @param offset
     *            The offset from which to start removing.
     * @param countThe
     *            number of 16-bit units to delete. If the sum of offset and
     *            count exceeds length then all 16-bit units from offset to the
     *            end of the data are deleted.
     * @throws DOMException
     *             INDEX_SIZE_ERR: Raised if the specified offset is negative or
     *             greater than the number of 16-bit units in data, or if the
     *             specified count is negative.
     */
    public void deleteText(int offset, int count) throws DOMException;

    /**
     * Replace the characters starting at the specified 16-bit unit offset with
     * the specified string.
     *
     * @param offset
     *            The offset from which to start replacing.
     * @param count
     *            The number of 16-bit units to replace. If the sum of offset
     *            and count exceeds length, then all 16-bit units to the end of
     *            the data are replaced; (i.e., the effect is the same as a
     *            remove method call with the same range, followed by an append
     *            method invocation).
     * @param text
     *            The DOMString with which the range must be replaced.
     * @throws DOMException
     *             INDEX_SIZE_ERR: Raised if the specified offset is negative or
     *             greater than the number of 16-bit units in data, or if the
     *             specified count is negative.
     */
    public void replaceText(int offset, int count, String text) throws DOMException;

    /**
     * Returns whether this text node content is empty("").
     * 
     * @return true if only whitespace content, false otherwise
     */
    boolean isContentEmpty();

} public class ConstantsUtil {

    public static final String COMMA = ",";
    public static final String COLON = ":";
    public static final String SEMICOLON = ";";
    public static final String DOT = ".";
    public static final String POUND = "#";
    public static final String STAR = "*";
    public static final String MD5 = "MD5";
    public static final String LEFT_PARENTHESIS = "(";
    public static final String RIGHT_PARENTHESIS = ")";
    public static final String LEFT_BRACE = "{";
    public static final String RIGHT_BRACE = "}";
    public static final String LESS_THAN = "<";
    public static final String GREATER_THAN = ">";
    public static final String RIGHT_ANGLE_BRACKET = GREATER_THAN;
    public static final String LEFT_ANGLE_BRACKET = LESS_THAN;
    public static final String IMG_PNG = "png";
    public static final String PLUS = "+";
    public static final String MINUS = "-";
    public static final String EQUAL = "=";
    public static final String EXCLAMATION = "!";
    public static final String DOUBLE_QUOTE = "\"";
    public static final String SINGLE_QUOTE = "'";
    public static String SLASH = "/";
    public static String BACKSLASH = "\\";
    public static String QUESTION_MARK = "?";
    public static final String TAB = "\t";

} public final class ListUtil {

    public static String[] toStringArray(final Collection<String> list) {
        if (list == null) {
            return null;
        }
        String[] array = new String[list.size()];
        return list.toArray(array);
    }

    public static String[] toStringArray(final List<?> list, final ListStringizer stringizer) {
        if (list == null) {
            return null;
        }
        String[] array = new String[list.size()];
        for (int i = 0; i < list.size(); i++) {
            array[i] = stringizer.element(list.get(i));
        }
        return array;
    }

    public static List<String> toStringList(final List<?> list, final ListStringizer stringizer) {
        if (list == null) {
            return null;
        }
        List<String> strList = list();
        for (int i = 0; i < list.size(); i++) {
            strList.add(stringizer.element(list.get(i)));
        }
        return strList;
    }

    public static Map<String, String> toStringMap(final List<?> list, final MapStringizer stringizer) {
        if (list == null) {
            return null;
        }
        Map<String, String> map = MapUtil.map();
        for (int i = 0; i < list.size(); i++) {
            map.put(stringizer.key(list.get(i)), stringizer.value(list.get(i)));
        }
        return map;
    }

    public static <T> List<T> toList(final T[] array) {
        List<T> l = list(array.length);
        l.addAll(Arrays.asList(array));
        return l;
    }

    public static <T> List<T> list(final int initialCapacity) {
        return new ArrayList<T>(initialCapacity);
    }

    public static <T> List<T> list() {
        return new ArrayList<T>();
    }

    @SafeVarargs
    public static <T> List<T> list(final T... objects) {
        List<T> l = list();
        l.addAll(toList(objects));
        return l;
    }

    public static boolean isNullOrEmptyList(final List<?> list) {
        return list == null || list.size() == 0;
    }

    public static boolean isNullList(final Collection<?> list) {
        return list == null;
    }

    public static <T> boolean isIndexOutOfBounds(final List<T> list, final int index) {
        return isNullList(list) || index >= 0 && index < list.size();
    }

    public static <T> void replace(final List<T> list, final T newElement, final int index) {
        if (!isIndexOutOfBounds(list, index)) {
            list.remove(index);
            list.add(index, newElement);
        }
    }

    public static boolean isEqualList(final List<?> one, final List<?> other) {
        return isEqualList(one, other, false);
    }

    public static boolean isEqualList(final List<?> one, final List<?> other, final boolean compareOrder) {
        if (one == other) {
            return true;
        }
        if (isNullList(one) || isNullList(other)) {
            return false;
        }
        if (one.size() != other.size()) {
            return false;
        }
        if (compareOrder) {
            Iterator<?> iter1 = one.iterator();
            Iterator<?> iter2 = other.iterator();
            while (iter1.hasNext() && iter2.hasNext()) {
                if (!ObjectUtil.isEqualObject(iter1.next(), iter2.next())) {
                    return false;
                }
            }
        } else {
            List<Integer> matchedIndex = ListUtil.list();
            andContinue: for (Object o1 : one) {
                for (int i = 0; i < other.size(); i++) {
                    if (matchedIndex.contains(i)) {
                        continue;
                    }
                    if (ObjectUtil.isEqualObject(o1, other.get(i), compareOrder)) {
                        matchedIndex.add(i);
                        break andContinue;
                    }
                }
                return false;
            }
        }
        return true;
    }

    public static <E> List<E> cloneList(final ArrayList<E> source) {
        return cloneList(source, false);
    }

    public static <E> List<E> cloneList(final ArrayList<E> source, final boolean deep) {
        if (!deep) {
            return ObjectUtils.clone(source);
        }
        if (isNullList(source)) {
            return null;
        }
        List<E> list = list(source.size());
        for (E e : source) {
            list.add(ObjectUtil.cloneObject(e, deep));
        }
        return list;
    }

}
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.lang3.CharEncoding;
import org.apache.commons.lang3.StringUtils;
import org.lttpp.eemory.Constants;
import org.lttpp.eemory.Messages;
import org.lttpp.eemory.dom.Attribute;
import org.lttpp.eemory.dom.DOMException;
import org.lttpp.eemory.dom.Document;
import org.lttpp.eemory.dom.DocumentFragment;
import org.lttpp.eemory.dom.DocumentType;
import org.lttpp.eemory.dom.Element;
import org.lttpp.eemory.dom.Node;
import org.lttpp.eemory.dom.Text;
import org.lttpp.eemory.util.ConstantsUtil;
import org.lttpp.eemory.util.DomUtil;
import org.lttpp.eemory.util.ListUtil;
package org.lttpp.eemory.dom.impl;



public class DocumentImpl extends NodeImpl implements Document {

    private boolean standalone;
    private String xmlVersion;
    private String encoding;

    protected DocumentImpl() {
        standalone = true;
        xmlVersion = Constants.XML_VERSION_1_0;
        encoding = CharEncoding.UTF_8;
    }

    @Override
    public Element getDocumentElement() {
        return (Element) getChildNodeByType(ELEMENT_NODE, DOCUMENT_FRAGMENT_NODE);
    }

    @Override
    public Element createElement(final String name) {
        ElementImpl e = new ElementImpl(name);
        e.setOwnerDocument(this);
        return e;
    }

    @Override
    public DocumentFragment createDocumentFragment() {
        DocumentFragmentImpl f = new DocumentFragmentImpl();
        f.setOwnerDocument(this);
        return f;
    }

    @Override
    public Text createTextNode(final String text) {
        TextImpl t = new TextImpl(text);
        t.setOwnerDocument(this);
        return t;
    }

    @Override
    public Attribute createAttribute(final String name) {
        AttributeImpl a = new AttributeImpl(name);
        a.setOwnerDocument(this);
        return a;
    }

    @Override
    public DocumentType createDocumentType(final String name, final String publicId, final String systemId) {
        DocumentTypeImpl t = new DocumentTypeImpl(name, publicId, systemId);
        t.setOwnerDocument(this);
        return t;
    }

    @Override
    public List<Node> getElementsByTagName(final String name) {
        if (name.equals(ConstantsUtil.STAR)) {
            return getChildNodes();
        } else {
            List<Node> matched = ListUtil.list();
            Iterator<Node> iter = getChildNodes().iterator();
            while (iter.hasNext()) {
                Node node = iter.next();
                if (node.getNodeName().equals(name)) {
                    matched.add(node);
                }
                if (node instanceof Element) {
                    matched.addAll(((Element) node).getElementsByTagName(name));
                }
            }
            return matched;
        }
    }

    @Override
    public String getInputEncoding() {
        return null;
    }

    @Override
    public String getXmlEncoding() {
        return encoding;
    }

    @Override
    public void setXMLEncoding(final String encoding) {
        this.encoding = encoding;
    }

    @Override
    public boolean getXmlStandalone() {
        return standalone;
    }

    @Override
    public void setXmlStandalone(final boolean standalone) {
        this.standalone = standalone;
    }

    @Override
    public String getXmlVersion() {
        return xmlVersion;
    }

    @Override
    public void setXmlVersion(final String xmlVersion) {
        this.xmlVersion = xmlVersion;
    }

    @Override
    public short getNodeType() {
        return Node.DOCUMENT_NODE;
    }

    @Override
    public boolean getStrictErrorChecking() {
        return true;
    }

    @Override
    public void setStrictErrorChecking(final boolean strictErrorChecking) {

    }

    @Override
    public Node importNode(final Node sourceNode, final boolean deep) throws DOMException {
        if (!canImport(sourceNode)) {
            throw new DOMException(DOMException.NOT_SUPPORTED_ERR, Messages.DOM_Error0);