text:
package org.apache.xerces.dom;

import org.apache.xerces.util.URI;
import org.w3c.dom.Attr;
import org.w3c.dom.DOMException;
import org.w3c.dom.Element;
import org.w3c.dom.ElementTraversal;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.w3c.dom.TypeInfo;

/**
 * Elements represent most of the "markup" and structure of the document. They contain both the data for the element
 * itself (element name and attributes), and any contained nodes, including document text (as children).
 *

 * Elements may have Attributes associated with them; the API for this is defined in Node, but the function is
 * implemented here. In general, XML applications should retrive Attributes as Nodes, since they may contain entity
 * references and hence be a fairly complex sub-tree. HTML users will be dealing with simple string values, and
 * convenience methods are provided to work in terms of Strings.
 *

 * ElementImpl does not support Namespaces. ElementNSImpl, which inherits from it, does.
 *
 * @xerces.internal
 *
 * @see ElementNSImpl
 *
 * @author Arnaud Le Hors, IBM
 * @author Joe Kesselman, IBM
 * @author Andy Clark, IBM
 * @author Ralf Pfeiffer, IBM
 * @author Michael Glavassevich, IBM
 * @version $Id: ElementImpl.java 938635 2010-04-27 20:23:42Z mrglavas $
 * @since PR-DOM-Level-1-19980818.
 */
public class ElementImpl extends ParentNode implements Element, ElementTraversal, TypeInfo {

	//
	// Constants
	//

	/** Serialization version. */
	static final long serialVersionUID = 3717253516652722278L;
	//
	// Data
	//

	/** Element name. */
	protected String name;

	/** Attributes. */
	protected AttributeMap attributes;

	//
	// Constructors
	//

	/** Factory constructor. */
	public ElementImpl(CoreDocumentImpl ownerDoc, String name) {
		super(ownerDoc);
		this.name = name;
		needsSyncData(true); // synchronizeData will initialize attributes
	}

	// for ElementNSImpl
	protected ElementImpl() {
	}

	// Support for DOM Level 3 renameNode method.
	// Note: This only deals with part of the pb. CoreDocumentImpl
	// does all the work.
	void rename(String name) {
		if (needsSyncData()) {
			synchronizeData();
		}
		if (ownerDocument.errorChecking) {
			int colon1 = name.indexOf(':');
			if (colon1 != -1) {
				String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null);
				throw new DOMException(DOMException.NAMESPACE_ERR, msg);
			}
			if (!CoreDocumentImpl.isXMLName(name, ownerDocument.isXML11Version())) {
				String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_CHARACTER_ERR",
						null);
				throw new DOMException(DOMException.INVALID_CHARACTER_ERR, msg);
			}
		}
		this.name = name;
		reconcileDefaultAttributes();
	}

	//
	// Node methods
	//

	/**
	 * A short integer indicating what type of node this is. The named constants for this value are defined in the
	 * org.w3c.dom.Node interface.
	 */
	public short getNodeType() {
		return Node.ELEMENT_NODE;
	}

	/**
	 * Returns the element name
	 */
	public String getNodeName() {
		if (needsSyncData()) {
			synchronizeData();
		}
		return name;
	}

	/**
	 * Retrieve all the Attributes as a set. Note that this API is inherited from Node rather than specified on Element;
	 * in fact only Elements will ever have Attributes, but they want to allow folks to "blindly" operate on the tree as
	 * a set of Nodes.
	 */
	public NamedNodeMap getAttributes() {

		if (needsSyncData()) {
			synchronizeData();
		}
		if (attributes == null) {
			attributes = new AttributeMap(this, null);
		}
		return attributes;

	} // getAttributes():NamedNodeMap

	/**
	 * Return a duplicate copy of this Element. Note that its children will not be copied unless the "deep" flag is
	 * true, but Attributes are always replicated.
	 *
	 * @see org.w3c.dom.Node#cloneNode(boolean)
	 */
	public Node cloneNode(boolean deep) {

		ElementImpl newnode = (ElementImpl) super.cloneNode(deep);
		// Replicate NamedNodeMap rather than sharing it.
		if (attributes != null) {
			newnode.attributes = (AttributeMap) attributes.cloneMap(newnode);
		}
		return newnode;

	} // cloneNode(boolean):Node

	/**
	 * DOM Level 3 WD - Experimental. Retrieve baseURI
	 */
	public String getBaseURI() {

		if (needsSyncData()) {
			synchronizeData();
		}
		// Absolute base URI is computed according to
		// XML Base (http://www.w3.org/TR/xmlbase/#granularity)
		// 1. The base URI specified by an xml:base attribute on the element,
		// if one exists
		if (attributes != null) {
			final Attr attrNode = getXMLBaseAttribute();
			if (attrNode != null) {
				final String uri = attrNode.getNodeValue();
				if (uri.length() != 0) {// attribute value is always empty string
					try {
						URI _uri = new URI(uri, true);
						// If the URI is already absolute return it; otherwise it's relative and we need to resolve it.
						if (_uri.isAbsoluteURI()) {
							return _uri.toString();
						}

						// Make any parentURI into a URI object to use with the URI(URI, String) constructor
						String parentBaseURI = (this.ownerNode != null) ? this.ownerNode.getBaseURI() : null;
						if (parentBaseURI != null) {
							try {
								URI _parentBaseURI = new URI(parentBaseURI);
								_uri.absolutize(_parentBaseURI);
								return _uri.toString();
							} catch (org.apache.xerces.util.URI.MalformedURIException ex) {
								// This should never happen: parent should have checked the URI and returned null if
								// invalid.
								return null;
							}
						}
						// REVISIT: what should happen in this case?
						return null;
					} catch (org.apache.xerces.util.URI.MalformedURIException ex) {
						return null;
					}
				}
			}
		}

		// 2.the base URI of the element's parent element within the
		// document or external entity, if one exists
		// 3. the base URI of the document entity or external entity
		// containing the element

		// ownerNode serves as a parent or as document
		return (this.ownerNode != null) ? this.ownerNode.getBaseURI() : null;
	} // getBaseURI

	/**
	 * NON-DOM Returns the xml:base attribute.
	 */
	protected Attr getXMLBaseAttribute() {
		return (Attr) attributes.getNamedItem("xml:base");
	} // getXMLBaseAttribute():Attr

	/**
	 * NON-DOM set the ownerDocument of this node, its children, and its attributes
	 */
	protected void setOwnerDocument(CoreDocumentImpl doc) {
		super.setOwnerDocument(doc);
		if (attributes != null) {
			attributes.setOwnerDocument(doc);
		}
	}

	//
	// Element methods
	//

	/**
	 * Look up a single Attribute by name. Returns the Attribute's string value, or an empty string (NOT null!) to
	 * indicate that the name did not map to a currently defined attribute.
	 *

	 * Note: Attributes may contain complex node trees. This method returns the "flattened" string obtained from
	 * Attribute.getValue(). If you need the structure information, see getAttributeNode().
	 */
	public String getAttribute(String name) {

		if (needsSyncData()) {
			synchronizeData();
		}
		if (attributes == null) {
			return "";
		}
		Attr attr = (Attr) (attributes.getNamedItem(name));
		return (attr == null) ? "" : attr.getValue();

	} // getAttribute(String):String

	/**
	 * Look up a single Attribute by name. Returns the Attribute Node, so its complete child tree is available. This
	 * could be important in XML, where the string rendering may not be sufficient information.
	 *

	 * If no matching attribute is available, returns null.
	 */
	public Attr getAttributeNode(String name) {

		if (needsSyncData()) {
			synchronizeData();
		}
		if (attributes == null) {
			return null;
		}
		return (Attr) attributes.getNamedItem(name);

	} // getAttributeNode(String):Attr

	/**
	 * Returns a NodeList of all descendent nodes (children, grandchildren, and so on) which are Elements and which have
	 * the specified tag name.
	 *

	 * Note: NodeList is a "live" view of the DOM. Its contents will change as the DOM changes, and alterations made to
	 * the NodeList will be reflected in the DOM.
	 *
	 * @param tagname The type of element to gather. To obtain a list of all elements no matter what their names, use
	 *            the wild-card tag name "*".
	 *
	 * @see DeepNodeListImpl
	 */
	public NodeList getElementsByTagName(String tagname) {
		return new DeepNodeListImpl(this, tagname);
	}

	/**
	 * Returns the name of the Element. Note that Element.nodeName() is defined to also return the tag name.
	 *

	 * This is case-preserving in XML. HTML should uppercasify it on the way in.
	 */
	public String getTagName() {
		if (needsSyncData()) {
			synchronizeData();
		}
		return name;
	}

	/**
	 * In "normal form" (as read from a source file), there will never be two Text children in succession. But DOM users
	 * may create successive Text nodes in the course of manipulating the document. Normalize walks the sub-tree and
	 * merges adjacent Texts, as if the DOM had been written out and read back in again. This simplifies implementation
	 * of higher-level functions that may want to assume that the document is in standard form.
	 *

	 * To normalize a Document, normalize its top-level Element child.
	 *

	 * As of PR-DOM-Level-1-19980818, CDATA -- despite being a subclass of Text -- is considered "markup" and will _not_
	 * be merged either with normal Text or with other CDATASections.
	 *
	 * <ScaleDOM> Note: Only loaded child nodes are normalized. </ScaleDOM>
	 */
	public void normalize() {
		// No need to normalize if already normalized.
		if (isNormalized()) {
			return;
		}
		if (needsSyncChildren()) {
			synchronizeChildren();
		}
		ChildNode kid, next;
		// <ScaleDOM>
		ChildNode firstChild = null;
		if(isScaleDomEnabled()) {
			firstChild = getFirstLoadedChildNode();
		} else {
			firstChild = this.firstChild;
		}
		// </ScaleDOM>
		for (kid = firstChild; kid != null; kid = next) {
			next = kid.nextSibling;

			// If kid is a text node, we need to check for one of two
			// conditions:
			// 1) There is an adjacent text node
			// 2) There is no adjacent text node, but kid is
			// an empty text node.
			if (kid.getNodeType() == Node.TEXT_NODE) {
				// If an adjacent text node, merge it with kid
				if (next != null && next.getNodeType() == Node.TEXT_NODE) {
					((Text) kid).appendData(next.getNodeValue());
					removeChild(next);
					next = kid; // Don't advance; there might be another.
				} else {
					// If kid is empty, remove it
					if (kid.getNodeValue() == null || kid.getNodeValue().length() == 0) {
						removeChild(kid);
					}
				}
			}

			// Otherwise it might be an Element, which is handled recursively
			else if (kid.getNodeType() == Node.ELEMENT_NODE) {
				kid.normalize();
			}
		}

		// We must also normalize all of the attributes
		if (attributes != null) {
			for (int i = 0; i < attributes.getLength(); ++i) {
				Node attr = attributes.item(i);
				attr.normalize();
			}
		}

		// changed() will have occurred when the removeChild() was done,
		// so does not have to be reissued.

		isNormalized(true);
	} // normalize()

	/**
	 * Remove the named attribute from this Element. If the removed Attribute has a default value, it is immediately
	 * replaced thereby.
	 *

	 * The default logic is actually implemented in NamedNodeMapImpl. PR-DOM-Level-1-19980818 doesn't fully address the
	 * DTD, so some of this behavior is likely to change in future versions. ?????
	 *

	 * Note that this call "succeeds" even if no attribute by this name existed -- unlike removeAttributeNode, which
	 * will throw a not-found exception in that case.
	 *
	 * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if the node is readonly.
	 */
	public void removeAttribute(String name) {

		if (ownerDocument.errorChecking && isReadOnly()) {
			String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
					"NO_MODIFICATION_ALLOWED_ERR", null);
			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
		}

		if (needsSyncData()) {
			synchronizeData();
		}

		if (attributes == null) {
			return;
		}

		attributes.safeRemoveNamedItem(name);

	} // removeAttribute(String)

	/**
	 * Remove the specified attribute/value pair. If the removed Attribute has a default value, it is immediately
	 * replaced.
	 *

	 * NOTE: Specifically removes THIS NODE -- not the node with this name, nor the node with these contents. If the
	 * specific Attribute object passed in is not stored in this Element, we throw a DOMException. If you really want to
	 * remove an attribute by name, use removeAttribute().
	 *
	 * @return the Attribute object that was removed.
	 * @throws DOMException(NOT_FOUND_ERR) if oldattr is not an attribute of this Element.
	 * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if the node is readonly.
	 */
	public Attr removeAttributeNode(Attr oldAttr) throws DOMException {

		if (ownerDocument.errorChecking && isReadOnly()) {
			String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
					"NO_MODIFICATION_ALLOWED_ERR", null);
			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
		}

		if (needsSyncData()) {
			synchronizeData();
		}

		if (attributes == null) {
			String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
			throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
		}
		return (Attr) attributes.removeItem(oldAttr, true);

	} // removeAttributeNode(Attr):Attr

	/**
	 * Add a new name/value pair, or replace the value of the existing attribute having that name.
	 *
	 * Note: this method supports only the simplest kind of Attribute, one whose value is a string contained in a single
	 * Text node. If you want to assert a more complex value (which XML permits, though HTML doesn't), see
	 * setAttributeNode().
	 *
	 * The attribute is created with specified=true, meaning it's an explicit value rather than inherited from the DTD
	 * as a default. Again, setAttributeNode can be used to achieve other results.
	 *
	 * @throws DOMException(INVALID_NAME_ERR) if the name is not acceptable. (Attribute factory will do that test for
	 *             us.)
	 *
	 * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if the node is readonly.
	 */
	public void setAttribute(String name, String value) {

		if (ownerDocument.errorChecking && isReadOnly()) {
			String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
					"NO_MODIFICATION_ALLOWED_ERR", null);
			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
		}

		if (needsSyncData()) {
			synchronizeData();
		}

		Attr newAttr = getAttributeNode(name);
		if (newAttr == null) {
			newAttr = getOwnerDocument().createAttribute(name);

			if (attributes == null) {
				attributes = new AttributeMap(this, null);
			}

			newAttr.setNodeValue(value);
			attributes.setNamedItem(newAttr);
		} else {
			newAttr.setNodeValue(value);
		}

	} // setAttribute(String,String)

	/**
	 * Add a new attribute/value pair, or replace the value of the existing attribute with that name.
	 *

	 * This method allows you to add an Attribute that has already been constructed, and hence avoids the limitations of
	 * the simple setAttribute() call. It can handle attribute values that have arbitrarily complex tree structure -- in
	 * particular, those which had entity references mixed into their text.
	 *
	 * @throws DOMException(INUSE_ATTRIBUTE_ERR) if the Attribute object has already been assigned to another Element.
	 */
	public Attr setAttributeNode(Attr newAttr) throws DOMException {

		if (needsSyncData()) {
			synchronizeData();
		}

		if (ownerDocument.errorChecking) {
			if (isReadOnly()) {
				String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
						"NO_MODIFICATION_ALLOWED_ERR", null);
				throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
			}

			if (newAttr.getOwnerDocument() != ownerDocument) {
				String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR",
						null);
				throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
			}
		}

		if (attributes == null) {
			attributes = new AttributeMap(this, null);
		}
		// This will throw INUSE if necessary
		return (Attr) attributes.setNamedItem(newAttr);

	} // setAttributeNode(Attr):Attr

	//
	// DOM2: Namespace methods
	//

	/**
	 * Introduced in DOM Level 2.
	 *

	 *
	 * Retrieves an attribute value by local name and namespace URI.
	 *
	 * @param namespaceURI The namespace URI of the attribute to retrieve.
	 * @param localName The local name of the attribute to retrieve.
	 * @return String The Attr value as a string, or empty string if that attribute does not have a specified or default
	 *         value.
	 * @since WD-DOM-Level-2-19990923
	 */
	public String getAttributeNS(String namespaceURI, String localName) {

		if (needsSyncData()) {
			synchronizeData();
		}

		if (attributes == null) {
			return "";
		}

		Attr attr = (Attr) (attributes.getNamedItemNS(namespaceURI, localName));
		return (attr == null) ? "" : attr.getValue();

	} // getAttributeNS(String,String):String

	/**
	 * Introduced in DOM Level 2.
	 *

	 *
	 * Adds a new attribute. If the given namespaceURI is null or an empty string and the qualifiedName has a prefix
	 * that is "xml", the new attribute is bound to the predefined namespace "http://www.w3.org/XML/1998/namespace"
	 * [Namespaces]. If an attribute with the same local name and namespace URI is already present on the element, its
	 * prefix is changed to be the prefix part of the qualifiedName, and its value is changed to be the value parameter.
	 * This value is a simple string, it is not parsed as it is being set. So any markup (such as syntax to be
	 * recognized as an entity reference) is treated as literal text, and needs to be appropriately escaped by the
	 * implementation when it is written out. In order to assign an attribute value that contains entity references, the
	 * user must create an Attr node plus any Text and EntityReference nodes, build the appropriate subtree, and use
	 * setAttributeNodeNS or setAttributeNode to assign it as the value of an attribute.
	 *
	 * @param namespaceURI The namespace URI of the attribute to create or alter.
	 * @param qualifiedName The qualified name of the attribute to create or alter.
	 * @param value The value to set in string form.
	 * @throws INVALID_CHARACTER_ERR: Raised if the specified name contains an invalid character.
	 *
	 * @throws NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
	 *
	 * @throws NAMESPACE_ERR: Raised if the qualifiedName has a prefix that is "xml" and the namespaceURI is neither
	 *             null nor an empty string nor "http://www.w3.org/XML/1998/namespace", or if the qualifiedName has a
	 *             prefix that is "xmlns" but the namespaceURI is neither null nor an empty string, or if if the
	 *             qualifiedName has a prefix different from "xml" and "xmlns" and the namespaceURI is null or an empty
	 *             string.
	 * @since WD-DOM-Level-2-19990923
	 */
	public void setAttributeNS(String namespaceURI, String qualifiedName, String value) {
		if (ownerDocument.errorChecking && isReadOnly()) {
			String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
					"NO_MODIFICATION_ALLOWED_ERR", null);
			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
		}
		if (needsSyncData()) {
			synchronizeData();
		}
		int index = qualifiedName.indexOf(':');
		String prefix, localName;
		if (index < 0) {
			prefix = null;
			localName = qualifiedName;
		} else {
			prefix = qualifiedName.substring(0, index);
			localName = qualifiedName.substring(index + 1);
		}
		Attr newAttr = getAttributeNodeNS(namespaceURI, localName);
		if (newAttr == null) {
			// REVISIT: this is not efficient, we are creating twice the same
			// strings for prefix and localName.
			newAttr = getOwnerDocument().createAttributeNS(namespaceURI, qualifiedName);
			if (attributes == null) {
				attributes = new AttributeMap(this, null);
			}
			newAttr.setNodeValue(value);
			attributes.setNamedItemNS(newAttr);
		} else {
			if (newAttr instanceof AttrNSImpl) {
				// change prefix and value
				((AttrNSImpl) newAttr).name = (prefix != null) ? (prefix + ":" + localName) : localName;
			} else {
				// This case may happen if user calls:
				// elem.setAttribute("name", "value");
				// elem.setAttributeNS(null, "name", "value");
				// This case is not defined by the DOM spec, we choose
				// to create a new attribute in this case and remove an old one from the tree
				// note this might cause events to be propagated or user data to be lost
				newAttr = ((CoreDocumentImpl) getOwnerDocument()).createAttributeNS(namespaceURI, qualifiedName,
						localName);
				attributes.setNamedItemNS(newAttr);
			}

			newAttr.setNodeValue(value);
		}

	} // setAttributeNS(String,String,String)

	/**
	 * Introduced in DOM Level 2.
	 *

	 *
	 * Removes an attribute by local name and namespace URI. If the removed attribute has a default value it is
	 * immediately replaced. The replacing attribute has the same namespace URI and local name, as well as the original
	 * prefix.
	 *

	 *
	 * @param namespaceURI The namespace URI of the attribute to remove.
	 *
	 * @param localName The local name of the attribute to remove.
	 * @throws NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
	 * @since WD-DOM-Level-2-19990923
	 */
	public void removeAttributeNS(String namespaceURI, String localName) {

		if (ownerDocument.errorChecking && isReadOnly()) {
			String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
					"NO_MODIFICATION_ALLOWED_ERR", null);
			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
		}

		if (needsSyncData()) {
			synchronizeData();
		}

		if (attributes == null) {
			return;
		}

		attributes.safeRemoveNamedItemNS(namespaceURI, localName);

	} // removeAttributeNS(String,String)

	/**
	 * Retrieves an Attr node by local name and namespace URI.
	 *
	 * @param namespaceURI The namespace URI of the attribute to retrieve.
	 * @param localName The local name of the attribute to retrieve.
	 * @return Attr The Attr node with the specified attribute local name and namespace URI or null if there is no such
	 *         attribute.
	 * @since WD-DOM-Level-2-19990923
	 */
	public Attr getAttributeNodeNS(String namespaceURI, String localName) {

		if (needsSyncData()) {
			synchronizeData();
		}
		if (attributes == null) {
			return null;
		}
		return (Attr) attributes.getNamedItemNS(namespaceURI, localName);

	} // getAttributeNodeNS(String,String):Attr

	/**
	 * Introduced in DOM Level 2.
	 *

	 *
	 * Adds a new attribute. If an attribute with that local name and namespace URI is already present in the element,
	 * it is replaced by the new one.
	 *
	 * @param newAttr The Attr node to add to the attribute list. When the Node has no namespaceURI, this method behaves
	 *            like setAttributeNode.
	 * @return Attr If the newAttr attribute replaces an existing attribute with the same local name and namespace URI,
	 *         the * previously existing Attr node is returned, otherwise null is returned.
	 * @throws WRONG_DOCUMENT_ERR: Raised if newAttr was created from a different document than the one that created the
	 *             element.
	 *
	 * @throws NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
	 *
	 * @throws INUSE_ATTRIBUTE_ERR: Raised if newAttr is already an attribute of another Element object. The DOM user
	 *             must explicitly clone Attr nodes to re-use them in other elements.
	 * @since WD-DOM-Level-2-19990923
	 */
	public Attr setAttributeNodeNS(Attr newAttr) throws DOMException {

		if (needsSyncData()) {
			synchronizeData();
		}
		if (ownerDocument.errorChecking) {
			if (isReadOnly()) {
				String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
						"NO_MODIFICATION_ALLOWED_ERR", null);
				throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
			}
			if (newAttr.getOwnerDocument() != ownerDocument) {
				String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR",
						null);
				throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
			}
		}

		if (attributes == null) {
			attributes = new AttributeMap(this, null);
		}
		// This will throw INUSE if necessary
		return (Attr) attributes.setNamedItemNS(newAttr);

	} // setAttributeNodeNS(Attr):Attr

	/**
	 * NON-DOM: sets attribute node for this element
	 */
	protected int setXercesAttributeNode(Attr attr) {

		if (needsSyncData()) {
			synchronizeData();
		}

		if (attributes == null) {
			attributes = new AttributeMap(this, null);
		}
		return attributes.addItem(attr);

	}

	/**
	 * NON-DOM: get inded of an attribute
	 */
	protected int getXercesAttribute(String namespaceURI, String localName) {

		if (needsSyncData()) {
			synchronizeData();
		}
		if (attributes == null) {
			return -1;
		}
		return attributes.getNamedItemIndex(namespaceURI, localName);

	}

	/**
	 * Introduced in DOM Level 2.
	 */
	public boolean hasAttributes() {
		if (needsSyncData()) {
			synchronizeData();
		}
		return (attributes != null && attributes.getLength() != 0);
	}

	/**
	 * Introduced in DOM Level 2.
	 */
	public boolean hasAttribute(String name) {
		return getAttributeNode(name) != null;
	}

	/**
	 * Introduced in DOM Level 2.
	 */
	public boolean hasAttributeNS(String namespaceURI, String localName) {
		return getAttributeNodeNS(namespaceURI, localName) != null;
	}

	/**
	 * Introduced in DOM Level 2.
	 *

	 *
	 * Returns a NodeList of all the Elements with a given local name and namespace URI in the order in which they would
	 * be encountered in a preorder traversal of the Document tree, starting from this node.
	 *
	 * @param namespaceURI The namespace URI of the elements to match on. The special value "*" matches all namespaces.
	 *            When it is null or an empty string, this method behaves like getElementsByTagName.
	 * @param localName The local name of the elements to match on. The special value "*" matches all local names.
	 * @return NodeList A new NodeList object containing all the matched Elements.
	 * @since WD-DOM-Level-2-19990923
	 */
	public NodeList getElementsByTagNameNS(String namespaceURI, String localName) {
		return new DeepNodeListImpl(this, namespaceURI, localName);
	}

	/**
	 * DOM Level 3 WD- Experimental. Override inherited behavior from NodeImpl and ParentNode to check on attributes
	 */
	public boolean isEqualNode(Node arg) {
		if (!super.isEqualNode(arg)) {
			return false;
		}
		boolean hasAttrs = hasAttributes();
		if (hasAttrs != ((Element) arg).hasAttributes()) {
			return false;
		}
		if (hasAttrs) {
			NamedNodeMap map1 = getAttributes();
			NamedNodeMap map2 = ((Element) arg).getAttributes();
			int len = map1.getLength();
			if (len != map2.getLength()) {
				return false;
			}
			for (int i = 0; i < len; i++) {
				Node n1 = map1.item(i);
				if (n1.getLocalName() == null) { // DOM Level 1 Node
					Node n2 = map2.getNamedItem(n1.getNodeName());
					if (n2 == null || !((NodeImpl) n1).isEqualNode(n2)) {
						return false;
					}
				} else {
					Node n2 = map2.getNamedItemNS(n1.getNamespaceURI(), n1.getLocalName());
					if (n2 == null || !((NodeImpl) n1).isEqualNode(n2)) {
						return false;
					}
				}
			}
		}
		return true;
	}

	/**
	 * DOM Level 3: register the given attribute node as an ID attribute
	 */
	public void setIdAttributeNode(Attr at, boolean makeId) {
		if (needsSyncData()) {
			synchronizeData();
		}
		if (ownerDocument.errorChecking) {
			if (isReadOnly()) {
				String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
						"NO_MODIFICATION_ALLOWED_ERR", null);
				throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
			}

			if (at.getOwnerElement() != this) {
				String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
				throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
			}
		}
		((AttrImpl) at).isIdAttribute(makeId);
		if (!makeId) {
			ownerDocument.removeIdentifier(at.getValue());
		} else {
			ownerDocument.putIdentifier(at.getValue(), this);
		}
	}

	/**
	 * DOM Level 3: register the given attribute node as an ID attribute
	 */
	public void setIdAttribute(String name, boolean makeId) {
		if (needsSyncData()) {
			synchronizeData();
		}
		Attr at = getAttributeNode(name);

		if (at == null) {
			String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
			throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
		}

		if (ownerDocument.errorChecking) {
			if (isReadOnly()) {
				String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
						"NO_MODIFICATION_ALLOWED_ERR", null);
				throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
			}

			if (at.getOwnerElement() != this) {
				String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
				throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
			}
		}

		((AttrImpl) at).isIdAttribute(makeId);
		if (!makeId) {
			ownerDocument.removeIdentifier(at.getValue());
		} else {
			ownerDocument.putIdentifier(at.getValue(), this);
		}
	}

	/**
	 * DOM Level 3: register the given attribute node as an ID attribute
	 */
	public void setIdAttributeNS(String namespaceURI, String localName, boolean makeId) {
		if (needsSyncData()) {
			synchronizeData();
		}
		Attr at = getAttributeNodeNS(namespaceURI, localName);

		if (at == null) {
			String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
			throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
		}

		if (ownerDocument.errorChecking) {
			if (isReadOnly()) {
				String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
						"NO_MODIFICATION_ALLOWED_ERR", null);
				throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
			}

			if (at.getOwnerElement() != this) {
				String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
				throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
			}
		}
		((AttrImpl) at).isIdAttribute(makeId);
		if (!makeId) {
			ownerDocument.removeIdentifier(at.getValue());
		} else {
			ownerDocument.putIdentifier(at.getValue(), this);
		}
	}

	/**
	 * @see org.w3c.dom.TypeInfo#getTypeName()
	 */
	public String getTypeName() {
		return null;
	}

	/**
	 * @see org.w3c.dom.TypeInfo#getTypeNamespace()
	 */
	public String getTypeNamespace() {
		return null;
	}

	/**
	 * Introduced in DOM Level 3.
	 *

	 * Checks if a type is derived from another by restriction. See:
	 * http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom
	 *
	 * @param typeNamespaceArg The namspace of the ancestor type declaration
	 * @param typeNameArg The name of the ancestor type declaration
	 * @param derivationMethod The derivation method
	 *
	 * @return boolean True if the type is derived by restriciton for the reference type
	 */
	public boolean isDerivedFrom(String typeNamespaceArg, String typeNameArg, int derivationMethod) {

		return false;
	}

	/**
	 * Method getSchemaTypeInfo.
	 *
	 * @return TypeInfo
	 */
	public TypeInfo getSchemaTypeInfo() {
		if (needsSyncData()) {
			synchronizeData();
		}
		return this;
	}

	//
	// Public methods
	//

	/**
	 * NON-DOM: Subclassed to flip the attributes' readonly switch as well.
	 *
	 * @see NodeImpl#setReadOnly
	 */
	public void setReadOnly(boolean readOnly, boolean deep) {
		super.setReadOnly(readOnly, deep);
		if (attributes != null) {
			attributes.setReadOnly(readOnly, true);
		}
	}

	//
	// Protected methods
	//

	/** Synchronizes the data (name and value) for fast nodes. */
	protected void synchronizeData() {

		// no need to sync in the future
		needsSyncData(false);

		// we don't want to generate any event for this so turn them off
		boolean orig = ownerDocument.getMutationEvents();
		ownerDocument.setMutationEvents(false);

		// attributes
		setupDefaultAttributes();

		// set mutation events flag back to its original value
		ownerDocument.setMutationEvents(orig);

	} // synchronizeData()

	// support for DOM Level 3 renameNode method
	// @param el The element from which to take the attributes
	void moveSpecifiedAttributes(ElementImpl el) {
		if (needsSyncData()) {
			synchronizeData();
		}
		if (el.hasAttributes()) {
			if (attributes == null) {
				attributes = new AttributeMap(this, null);
			}
			attributes.moveSpecifiedAttributes(el.attributes);
		}
	}

	/** Setup the default attributes. */
	protected void setupDefaultAttributes() {
		NamedNodeMapImpl defaults = getDefaultAttributes();
		if (defaults != null) {
			attributes = new AttributeMap(this, defaults);
		}
	}

	/** Reconcile default attributes. */
	protected void reconcileDefaultAttributes() {
		if (attributes != null) {
			NamedNodeMapImpl defaults = getDefaultAttributes();
			attributes.reconcileDefaults(defaults);
		}
	}

	/** Get the default attributes. */
	protected NamedNodeMapImpl getDefaultAttributes() {

		DocumentTypeImpl doctype = (DocumentTypeImpl) ownerDocument.getDoctype();
		if (doctype == null) {
			return null;
		}
		ElementDefinitionImpl eldef = (ElementDefinitionImpl) doctype.getElements().getNamedItem(getNodeName());
		if (eldef == null) {
			return null;
		}
		return (NamedNodeMapImpl) eldef.getAttributes();

	} // getDefaultAttributes()

	//
	// ElementTraversal methods
	//

	/**
	 * @see  Element
	 *      Traversal Specification
	 */
	public final int getChildElementCount() {
		int count = 0;
		Element child = getFirstElementChild();
		while (child != null) {
			++count;
			child = ((ElementImpl) child).getNextElementSibling();
		}
		return count;
	} // getChildElementCount():int

	/**
	 * @see  Element
	 *      Traversal Specification
	 */
	public final Element getFirstElementChild() {
		Node n = getFirstChild();
		while (n != null) {
			switch (n.getNodeType()) {
			case Node.ELEMENT_NODE:
				return (Element) n;
			case Node.ENTITY_REFERENCE_NODE:
				final Element e = getFirstElementChild(n);
				if (e != null) {
					return e;
				}
				break;
			}
			n = n.getNextSibling();
		}
		return null;
	} // getFirstElementChild():Element

	/**
	 * @see  Element
	 *      Traversal Specification
	 */
	public final Element getLastElementChild() {
		Node n = getLastChild();
		while (n != null) {
			switch (n.getNodeType()) {
			case Node.ELEMENT_NODE:
				return (Element) n;
			case Node.ENTITY_REFERENCE_NODE:
				final Element e = getLastElementChild(n);
				if (e != null) {
					return e;
				}
				break;
			}
			n = n.getPreviousSibling();
		}
		return null;
	} // getLastElementChild():Element

	/**
	 * @see  Element
	 *      Traversal Specification
	 */
	public final Element getNextElementSibling() {
		Node n = getNextLogicalSibling(this);
		while (n != null) {
			switch (n.getNodeType()) {
			case Node.ELEMENT_NODE:
				return (Element) n;
			case Node.ENTITY_REFERENCE_NODE:
				final Element e = getFirstElementChild(n);
				if (e != null) {
					return e;
				}
				break;
			}
			n = getNextLogicalSibling(n);
		}
		return null;
	} // getNextElementSibling():Element

	/**
	 * @see  Element
	 *      Traversal Specification
	 */
	public final Element getPreviousElementSibling() {
		Node n = getPreviousLogicalSibling(this);
		while (n != null) {
			switch (n.getNodeType()) {
			case Node.ELEMENT_NODE:
				return (Element) n;
			case Node.ENTITY_REFERENCE_NODE:
				final Element e = getLastElementChild(n);
				if (e != null) {
					return e;
				}
				break;
			}
			n = getPreviousLogicalSibling(n);
		}
		return null;
	} // getPreviousElementSibling():Element

	// Returns the first element node found from a
	// non-recursive in order traversal of the given node.
	private Element getFirstElementChild(Node n) {
		final Node top = n;
		while (n != null) {
			if (n.getNodeType() == Node.ELEMENT_NODE) {
				return (Element) n;
			}
			Node next = n.getFirstChild();
			while (next == null) {
				if (top == n) {
					break;
				}
				next = n.getNextSibling();
				if (next == null) {
					n = n.getParentNode();
					if (n == null || top == n) {
						return null;
					}
				}
			}
			n = next;
		}
		return null;
	} // getFirstElementChild(Node):Element

	// Returns the first element node found from a
	// non-recursive reverse order traversal of the given node.
	private Element getLastElementChild(Node n) {
		final Node top = n;
		while (n != null) {
			if (n.getNodeType() == Node.ELEMENT_NODE) {
				return (Element) n;
			}
			Node next = n.getLastChild();
			while (next == null) {
				if (top == n) {
					break;
				}
				next = n.getPreviousSibling();
				if (next == null) {
					n = n.getParentNode();
					if (n == null || top == n) {
						return null;
					}
				}
			}
			n = next;
		}
		return null;
	} // getLastElementChild(Node):Element

	// Returns the next logical sibling with respect to the given node.
	private Node getNextLogicalSibling(Node n) {
		Node next = n.getNextSibling();
		// If "n" has no following sibling and its parent is an entity reference node we
		// need to continue the search through the following siblings of the entity
		// reference as these are logically siblings of the given node.
		if (next == null) {
			Node parent = n.getParentNode();
			while (parent != null && parent.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
				next = parent.getNextSibling();
				if (next != null) {
					break;
				}
				parent = parent.getParentNode();
			}
		}
		return next;
	} // getNextLogicalSibling(Node):Node

	// Returns the previous logical sibling with respect to the given node.
	private Node getPreviousLogicalSibling(Node n) {
		Node prev = n.getPreviousSibling();
		// If "n" has no previous sibling and its parent is an entity reference node we
		// need to continue the search through the previous siblings of the entity
		// reference as these are logically siblings of the given node.
		if (prev == null) {
			Node parent = n.getParentNode();
			while (parent != null && parent.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
				prev = parent.getPreviousSibling();
				if (prev != null) {
					break;
				}
				parent = parent.getParentNode();
			}
		}
		return prev;
	} // getPreviousLogicalSibling(Node):Node

} // class ElementImpl


text:
/*jshint immed: false */

'use strict';

/**
 * Using mock for connect.
 * Mock includes additional methods for testing as .get(), .end(), etc.
 * To be able to check http respond right away
 *
 * Example:
 *
 *     http.middleware.request().get('/favicon.ico').end(function(res) {
 *         res.statusCode.should.equal(200);
 *         ac.check(done);
 *     });
 *
 */

var request      = require('supertest'),
    path         = require('path'),
    connect      = require('connect'),
    util         = require('util'),
    ac           = require('../../helpers/assertionCounter'),
    httpFunc     = require( path.join(process.env.PWD, 'lib/http/index') ),
    http         = null,
    app          = null,
    utils        = require('../../helpers/utils.js'),
    sessionStore = new connect.session.MemoryStore,
    settings     = {        // User-configurable settings with sensible defaults
      "static": {
        maxAge: 2592000000    // (30 * 24 * 60 * 60 * 1000) cache static assets in the browser for 30 days
      },
      secure: false           // allow setting of the 'secure' cookie attribute when using SSL - see https://github.com/socketstream/socketstream/issues/349
    },
    sessionOptions = {
        maxAge: 2592000000
    },
    root           = path.join(process.cwd(), 'test/fixtures/project'); // replace '\' with '/' to support Windows

describe('lib/http/index', function () {

    beforeEach(function (done) {
        http = httpFunc(root);
        done();
    });

    describe('module.exports', function () {
        it('should return a function instance', function (done) {
            ac.expect(1);

            httpFunc.should.be.type('function').andCheck();
            ac.check(done);
        });
    });

    describe('module.exports()', function () {
        it('should return an http object instance', function (done) {
            ac.expect(4);
            http.should.be.type('object').with.properties('set', 'load', 'route').andCheck();
            http.set.should.be.type('function').andCheck();
            http.load.should.be.type('function').andCheck();
            http.route.should.be.type('function').andCheck();

            ac.check(done);
        });

        describe('#set()', function () {
            beforeEach(function (done) {
              http = httpFunc(root);
              done();
            });

            it('should set newSettings into the private settings object', function (done) {
                var newSettings = {
                    secure: true
                };

                ac.expect(0);
                /* Should now throw an error */
                http.set(newSettings);
                ac.check(done);
            });

            it('should throw an error if passed argument is not an object', function (done) {
                var newSettings = '';

                ac.expect(0);

                /* Should throw an error */
                (function() {
                    http.set(newSettings);
                }).should.throw('ss.http.set() takes an object e.g. {static: {maxAge: 60000}}');

                ac.check(done);
            });
        });

        describe('#route()', function () {
            var obj;

            beforeEach(function(done) {
                obj  = null;
                http = httpFunc(root);
                done();
            });

            it('should add event listener for given url', function (done) {
                function callback(req, res) {
                    res.serve('main');
                }

                ac.expect(6);

                obj = http.route('/', callback);

                obj.should.be.an.instanceOf(Object).andCheck();
                obj._events.should.be.an.instanceOf(Object).andCheck();
                obj.listenerTree.should.be.an.instanceOf(Object).andCheck();
                obj.listenerTree['/'].should.be.an.instanceOf(Object).andCheck();
                obj.listenerTree['/']._listeners.should.be.an.instanceOf(Object).andCheck();
                obj.listenerTree['/']._listeners.toString().should.include(callback.toString()).andCheck();

                ac.check(done);
            });

            it('should add default event listener for the url with out callback', function (done) {
                var router,
                    url,
                    callback = function(name) {
                        return router.on(url, function(req, res) {
                            return res.serveClient(name);
                        });
                    }

                ac.expect(3);

                obj = http.route('/');

                obj.should.be.an.instanceOf(Object).andCheck();
                obj.serveClient.should.be.an.instanceOf(Object).andCheck();
                obj.serveClient.toString().replace(/(\s+|\n)/g, ' ').should.include(callback.toString().replace(/(\s+|\n)/g, ' ')).andCheck();

                ac.check(done);
            });

            it('should throw an error if does not start with \'/\'', function (done) {
                var url = 'some_url_wwith_no_slash_at_the_start';

                function callback(req, res) {
                    res.serve('main');
                }

                ac.expect(0);

                (function() {
                    http.route(url, callback);

                }).should.throw( util.format('%s is not a valid URL. Valid URLs must start with /', url) );

                ac.check(done);
            });
        });

        describe('#load()', function () {
            var staticPath = '';

            function setUp(done) {
                staticPath = 'client/static';

                /* Loading http function */
                http = httpFunc(root);

                /* adding some test middlewars */
                http.middleware.prepend(testPrependMiddleware);
                http.middleware.append(testAppendMiddleware);

                /* loading http server assets */
                app = http.load(staticPath, sessionStore, sessionOptions);

                done();
            }

            function testPrependMiddleware(req, res, next) {
                next();
            }

            function testAppendMiddleware(req, res, next) {
                if (req) {
                    next();
                }
            }

            beforeEach(setUp);

            /**
             * connect.compress() should be added to middleware stack on highest possible position
             */
            it('should build propper middleware stack', function (done) {
                ac.expect(18);

                /* testing correct length of http.middleware.stack */
                http.middleware.stack.should.be.an.instanceOf(Array).andCheck();
                http.middleware.stack.should.have.length(8).andCheck();

                /**
                 * testing testPrependMiddleware
                 * lib/http/index.js:104
                 */
                http.middleware.stack[0].handle.should.be.an.instanceOf(Function).andCheck();
                http.middleware.stack[0].handle.toString().should.equal( testPrependMiddleware.toString() ).andCheck();

                /**
                 * testing connect.compress()
                 * It should be added to middleware stack on highest possible position
                 * lib/http/index.js:142
                 */
                http.middleware.stack[1].handle.should.be.an.instanceOf(Function).andCheck();
                http.middleware.stack[1].handle.toString().should.equal( connect.compress().toString() ).andCheck();

                /**
                 * testing connect.cookieParser('SocketStream')
                 * lib/http/index.js:145
                 */
                http.middleware.stack[2].handle.should.be.an.instanceOf(Function).andCheck();
                http.middleware.stack[2].handle.toString().should.equal( connect.cookieParser('SocketStream').toString() ).andCheck();

                /**
                 * testing connect.favicon()
                 * lib/http/index.js:145
                 */
                http.middleware.stack[3].handle.should.be.an.instanceOf(Function).andCheck();
                http.middleware.stack[3].handle.toString().should.equal( connect.favicon( staticPath + '/favicon.ico').toString() ).andCheck();

                /**
                 * testing connect.session()
                 * lib/http/index.js:145
                 */
                http.middleware.stack[4].handle.should.be.an.instanceOf(Function).andCheck();
                http.middleware.stack[4].handle.toString().should.equal( connect.session({
                    cookie: {
                        path: '/',
                        httpOnly: false,
                        maxAge: sessionOptions.maxAge,
                        secure: settings.secure
                    },
                    store: sessionStore
                }).toString() ).andCheck();

                /**
                 * testing testAppendMiddleware
                 * lib/http/index.js:156
                 */
                http.middleware.stack[5].handle.should.be.an.instanceOf(Function).andCheck();
                http.middleware.stack[5].handle.toString().should.equal( testAppendMiddleware.toString() ).andCheck();

                /**
                 * testing eventMiddleware
                 * since there ra no way to get the instance of eventMiddleware function,
                 * just compare the functions names
                 * lib/http/index.js:161
                 */
                http.middleware.stack[6].handle.should.be.an.instanceOf(Function).andCheck();
                utils.getfunctionName( http.middleware.stack[6].handle ).should.equal( 'eventMiddleware' ).andCheck();

                /**
                 * testing connect["static"]()
                 * lib/http/index.js:161
                 */
                http.middleware.stack[7].handle.should.be.an.instanceOf(Function).andCheck();
                http.middleware.stack[7].handle.toString().should.equal( connect["static"](staticPath, settings["static"]).toString() ).andCheck();

                ac.check(done);
            });

            describe('returned app/http object', function () {
                beforeEach(setUp);

                it('should be an instance of Object', function (done) {
                    ac.expect(1);
                    app.should.be.an.instanceOf(Object).andCheck();
                    ac.check(done);
                });

                it('should respond with status 200 for /favicon.ico request', function (done) {
                    ac.expect(1);

                    request(app).get('/favicon.ico').end(function(err, res) {
                        res.statusCode.should.equal(200).andCheck();
                        ac.check(done);
                    });
                });
            });
        });
    });

});

redpajama_set_name: RedPajamaGithub


text:
\chapter{Results and Discussion}\label{results}
%All our results are in ones and zeroes.
%And further we discuss why there are only zeroes. And how that affects the
%outcome and future endeavors for the pirates we are.

In this chapter we present the results of our research and a concluding
discussion.
We discuss the core parts of the thesis. The data sources,
section \ref{results:data_sources}. Dictionaries, section
\ref{results:dictionaries}. Classification of sentiment in section
\ref{results:classification}, and the trend in section \ref{results:trend}. Last
we have a general discussion about the results.
%

\section{Data Source}\label{results:data_sources}
The use of Twitter as a data source proved to be good. It was easy to obtain
data, but it was difficult to get good amounts of data and unbiased data. The
initial data have some restriction to search words. We
should have mined, and classified more data.

The dictionaries worked well. We have different results for
different dictionaries and different datasets, but the way to
compile datasets work good. The dictionaries depend on the manually classified
tweets, so a lot of the potential improvement lies there. We can
improve the dictionaries by removing stop words and other words that we know
have no clear positive or negative sentiment.

In research question 1, we asked what knowledge we can
extract from tweets to find a sentiment.

The dictionaries are a good way of collecting information about sentiment, for
collections of manually labeled tweets.
The combined sentiment of a dataset is in many ways described in a set of
dictionaries.

Research question 3, asks if Twitter has been useful in
comparison to technical analysis. To some extent it has.
The data from Twitter has been
used to acquire positive and negative tweets for the trend aggregation, and has
also provided useful insight into the use of the Twitter API.
%

\section{Dictionaries}\label{results:dictionaries}
As for the use of the dictionaries in association with the trend, and research
question 3, we used the dictionaries for feature
extraction in the classifiers, previously described in section
\ref{sentiment:classifier_classification}. Besides the use in classifiers the
dictionaries have no practical uses in this thesis in relation to sentiment.

\paragraph{Error analysis}
\hspace{0pt}\\
When looking at the duplicate words\footnote{File With duplicate words:
\url{https://github.com/magnuskiro/master/blob/master/code/dictionaries/duplicate-words-from-monogram-compilation.txt}}
from the monogram dictionary based on the Kiro dataset we found some errors.
Some of the words found was: \textit{dangerous, bad, go, inc, let, up, or, need,
good, if, no, are, and, of, on, the, is, as}.

We found the words \textit{good} and \textit{bad}.
This is not good. By removing the words from the dictionaries we have removed
significant words from further classifications, thus reducing correctness of the
algorithm. This is one of the drawbacks of the monogram dictionaries.

When looking at the removed duplicate words for bigram and trigrams we found no
indication of the same problem. As the uniqueness of bigrams and trigrams are a
lot greater we end up with very few duplicates and only duplicates that has no
significance to the over all classification. Although we might have other
unknown problems.

Most stop words and other insignificant words are removed with the removal of
duplicate words. The same thing cannot be said about the bigram and trigram
dictionaries. There we have no stop words present, but they are
frequently part of other words. For further improvements of classification with
word counting, and dictionary quality we should remove
stop words, such as \textit{as, is, on, off, and, or} etc, from the
tweet/sentence before creating bi-, and trigrams.
%

\section{Classification}\label{results:classification}
Manual labeling is a challenge. The whole
classification process is based on personal opinion, which makes the results
somewhat biased. To eliminate this error we should have multiple people do the
same manual classification and combine the results.

Word counting works to some extent. But presents varied results based on the
dataset and the dictionary used. This is because of the dataset and the
dictionaries created. Also the way we separate tweets from each other with a
threshold can be improved. Word counting works, but it is not very
good.

Classifiers  improve the classification quite a bit. With the SVM classifier we
get around 98 percent correct classification on both data sets.

The uncertainties lie in the biased, or potentially biased, data. We do not
know if the data itself is fully representative for the content on Twitter.
Neither do we know if the manual classification is completely correct.

In total we gained some knowledge about dictionaries and their effect on
classification. We can confirm that classifiers work better than word
counting.

We tested two methods for finding the sentiment of a tweet: the bag of words
method described in section \ref{sentiment:word_count_classification}, and the
trained classifiers with the SVM and Naive Bayes classifiers,
\ref{sentiment:classification}.

In relation to research question 2, the question about trend
aggregation, we found that the sentiment classification was successful. This is
shown in tabled \ref{tbl:classification_comparison}, on page
\pageref{tbl:classification_comparison}.
The sentiment worked to some extent. We do not
know how well, and we have to look into the part of credibility in future work.
%

\subsection{Word Count Classification}\label{results:word_count_classification}
The results from the word count classification is plotted in the tabled
\ref{tbl:sentiment_word_count_results}, page
\pageref{tbl:sentiment_word_count_results}, and in the graph
\ref{fig:dictionary_accyracy}, page \pageref{fig:dictionary_accyracy}.

\begin{table}
\centering
\label{tbl:sentiment_word_count_results}
\caption{Word Count Classification Results}
\begin{tabular}{ r p{6cm} r r c }
id & Dictionary & Failed & Correct & Accuracy \\
& -- Kiro compiled dataset -- & a & b & b/(a+b) \\
\hline
1 & Monogram, Obama & 578 & 419 & 0.4203 \\
2 & Monogram LoughranMcDonald & 491 & 506 & 0.5075 \\
3 & Monogram, combined Obama and LoughranMcDonald & 416 & 581 & 0.5827 \\
4 & Kiro, Monogram, self compiled & 115 & 882 & 0.8847 \\
5 & Kiro, Bigram, self compiled & 17 & 980 & 0.9829 \\
6 & Kiro, Trigram, self compiled & 18 & 979 & 0.9819 \\
7 & Obama, Monogram, self compiled & 567 & 430 & 0.4313 \\
8 & Obama Bigram, self compiled & 534 & 463 & 0.4644 \\
9 & Obama Trigram, self compiled & 567 & 430 & 0.4313 \\
& -- Obama tweet set -- & a & b & b/(a+b) \\
\hline
10 & Monogram, Obama & 855 & 510 & 0.3736 \\
11 & Monogram LoughranMcDonald & 508 & 857 & 0.6278 \\
12 & Monogram, combined Obama and LoughranMcDonald & 544 & 821 & 0.6015 \\
13 & Kiro, Monogram, self compiled & 632 & 733 & 0.5370 \\
14 & Kiro, Bigram, self compiled & 521 & 844 & 0.6183 \\
15 & Kiro, Trigram, self compiled & 498 & 867 & 0.6352 \\
16 & Obama, Monogram, self compiled & 493 & 872 & 0.6388 \\
17 & Obama Bigram, self compiled & 37 & 1328 & 0.9729 \\
18 & Obama Trigram, self compiled & 39 & 1326 & 0.9714 \\
\end{tabular}
\end{table}

In table \ref{tbl:sentiment_word_count_results}, page
\pageref{tbl:sentiment_word_count_results}, id 5, 6, 17, and 18 are the
dictionaries with best accuracy. This is expected for the classification
of the dataset the dictionary was created from.

We take the results for dictionaries created form one dataset,
and look at the results of the classification on the other dataset. From table
\ref{tbl:sentiment_word_count_results} we compared id
7, 8, 9 with each other and 13, 14, 15 with each other. Then we can see that
the bigram and trigram dictionaries perform better than the monogram
dictionaries.

Further we see indications that the quality of the dictionary plays an
important role. The LoguhranMcDonald monogram dictionary performs quite good
with both datasets. Even on par with the compiled dictionaries on opposite
dataset. This indicates that a well crafted dictionary can perform as well
as compiled dictionaries, and vice versa.

\begin{figure}[htb]
    \centering
    \includegraphics[width=\textwidth]{dictionary_accyracy.png}
    \label{fig:dictionary_accyracy}
    \caption{Dictionary Accuracy plot}
The graph shows the plotted accuracies from the word count
classification. The ids represents the ids from table
\ref{tbl:sentiment_word_count_results}, page
\pageref{tbl:sentiment_word_count_results}
\end{figure}

When comparing the results from one dataset with the other we can see indications
of how the content of the dataset also plays a huge role in the results. Some
tweets are more difficult to classify then others.

There are a lot of improvements that could be done.
The word count classification is merely a convenient way to say something about
the dictionaries used. We should expand our knowledge toward the quality of the
dictionaries. And look for ways to eliminate words that are neither positive or
negative.

\subsection{Threshold Variation}\label{results:threshold}
Further we found the best average threshold value to be 0.1.
From table \ref{tbl:average_threshold_accuracy}, page \pageref{tbl:average_threshold_accuracy}, we have the threshold value, and the average
classification accuracy among the 18 entries for each threshold value.

\begin{table}
\centering
\label{tbl:average_threshold_accuracy}
\caption{Average Threshold Accuracy}
\begin{tabular}{ c c c c }
Threshold & Accuracy & Threshold & Accuracy \\
\hline
- & - & 0.0 & 0.6479 \\
-0.1 & 0.6316 & 0.1 & 0.6516 \\
-0.2 & 0.6161 & 0.2 & 0.6511 \\
-0.3 & 0.6059 & 0.3 & 0.6430 \\
-0.4 & 0.5988 & 0.4 & 0.6305 \\
-0.5 & 0.5888 & 0.5 & 0.6122 \\
-0.6 & 0.5711 & 0.6 & 0.5934 \\
-0.7 & 0.5423 & 0.7 & 0.5712 \\
-0.8 & 0.5083 & 0.8 & 0.5457 \\
-0.9 & 0.4881 & 0.9 & 0.5307 \\
\end{tabular}
\end{table}

\begin{figure}[htb]
    \centering
    \includegraphics[width=\textwidth]{average_threshold_accuracy.png}
    \label{fig:average_threshold_accuracy}
    \caption{Average Threshold Accuracy}
Graph plots of the 'Average threshold accuracy' table.
\end{figure}

In figure \ref{fig:threshold_graphs}, page \pageref{fig:threshold_graphs}, we list the results of the experimentation
with the threshold. Table \ref{tbl:dictionary_to_threshold}, page
\pageref{tbl:dictionary_to_threshold}, lists the
dictionaries and dataset used for which graphs in figure
\ref{fig:threshold_graphs}, page \pageref{fig:threshold_graphs}.
'Kiro dataset' and 'Obama dataset' columns tells which dataset that was
classified in which graph.

\begin{table}
\centering
\label{tbl:dictionary_to_threshold}
\caption{Dictionary to Threshold graph plot values}
\begin{tabular}{ l c c }
Dictionary name and description & Kiro dataset & Obama dataset \\
\hline
Obama original, Monogram & 1 & 10 \\
LoughranMcDonald, Monogram & 2 & 11 \\
Combined Obama original and \\ LoughranMcDonald, Monogram & 3 & 12 \\
Kiro, Monogram, self compiled & 4 & 13 \\
Obama, Monogram, self compiled & 5 & 14 \\
Kiro, Bigram, self compiled & 6 & 15 \\
Obama, Bigram, self compiled & 7 & 16 \\
Kiro, Trigram, self compiled & 8 & 17 \\
Obama, Trigram, self compiled & 9 & 18 \\
\end{tabular}
\end{table}

\begin{figure}[htb]
    \centering
    \includegraphics[width=\textwidth]{threshold_graphs.png}
    \label{fig:threshold_graphs}
    \caption{Threshold Variation Accuracy}
The graphs plot the different variations of threshold. Counting is
columns first; top left is 1, top mid is 7, top right is 13.
\end{figure}

\subsection{Using Classifiers}
Not surprisingly the classifiers have better results than the bag of words
method of classification, see table \ref{tbl:classification_comparison}, page
\pageref{tbl:classification_comparison}. Further the SVM classifier with the LinearSVC kernel
module performed best. Naive Bayes classifier was nearly as good. This answers
part of research question 1, \ref{introduction:rq1}.

\paragraph{SVM}\label{results:svm_classification}
\hspace{0pt}\\
From results of the experiment in section \ref{experiments:svm_classification},
we can draw some conclusions. The monogram dictionary performed
better than the bigram dictionary. Probably due to the number of features we
can extract from each tweet. Classifiers are more accurate than the word
count classification method.

\paragraph{Naive Bayes}\label{results:naive_bayes_classification}
\hspace{0pt}\\
As we can see from the experiment, section
\ref{experiments:naive_bayes_classification}, the different dictionaries makes
no difference for the Naive Bayes classifier. But if we compare the classifier
with the results from the word count classification we can clearly see
improvement. Naive Bayes did not perform as good as SVM.

\subsection{Comparison}\label{results:comparison}
In table, \ref{tbl:classification_comparison}, page
\pageref{tbl:classification_comparison}, we highlight the
results from the different classifications. We list the most noteworthy results
from our experiments and compare them.

\begin{table}
\centering
\label{tbl:classification_comparison}
\caption{Comparison of Classifiers}
Here we highlight the best results from classification tests.
\begin{tabular}{ l l p{3.5cm} r r c }
Classifier & Dataset & Dictionary & Failed & Correct & Accuracy \\
\hline
Word Count & Kiro & Obama Bigram & 534 & 463 & 0.4644 \\
Word Count & Obama & LoughranMcDonald Monogram & 508 & 857 & 0.6278 \\
Word Count & Obama & Kiro, Trigram & 498 & 867 & 0.6352 \\
Naive Bayes & Kiro & Kiro Monogram & 29 & 968 & 0.9709 \\
SVM & Kiro & Kiro Monogram & 7 & 990 & 0.9930 \\
\end{tabular}
\end{table}

As we can see the classifiers give better results then the word count
classification. And SVM is a bit better than Naive Bayes. Although the results
from the word count classification indicates that the dictionaries play an
important role in the results. We can also see that monograms are better for
classifiers, while trigrams are better for word counting.

For the trained classifiers, the more
features we have the easier it is to classify, and the more accurate the
results are.
%

\section{The Trend}\label{results:trend}
Comparing the two graph plots, figure \ref{fig:trend_finance_plot}, page
\pageref{fig:trend_finance_plot}, and figure
\ref{fig:trend_tweet_plot}, page \pageref{fig:trend_tweet_plot}, we can see minor similarities. All the moving
averages have rightward growth. While for the tweet trend the 3 day interval
preforms worse than the 8 day interval. There are no certain correlations
between the two trends. And it is difficult to conclude on specifics.

Research questions(RQ), 2(\ref{introduction:rq2}), and
3(\ref{introduction:rq3}) are in some degree true. RQ2, we can aggregate a
trend, the use for it and the accuracy we know nothing of. RQ3 has the
answer 'poor'. The sentiment trend compares poorly to the trend from the technical
analysis.

\paragraph{Finance plot}
\hspace{0pt}\\
The plotting of the graph is described in better detail in appendix
\ref{code:trend_aggregation}, page \pageref{code:trend_aggregation}.

Plotting the finance trend we got figure \ref{fig:trend_finance_plot}, page
\pageref{fig:trend_finance_plot}.

\begin{figure}[htb]
    \centering
    \includegraphics[width=\textwidth]{finance_trend_plot.png}
    \label{fig:trend_finance_plot}
    \caption{Finance trend plot}
This is the plot for OSEBX. The plot show the moving average in the middle and
the Average directional graph at the bottom. Time frame: Apr 26 - May 26.

The blue line in the top part shows the moving average with 8 days as the
average time frame. The white line has a 3 day time frame.

The bottom part show three lines, red, green, and white. The red is reduction
in price. The green is increase in price. The white one is the ADX.
\end{figure}

\paragraph{Twitter plot}
\hspace{0pt}\\
Code for plotting the trend graph is described in appendix
\ref{code:trend_aggregation}, page \pageref{code:trend_aggregation}.

Plotting the moving average for the Twitter trend we get figure:
\ref{fig:trend_tweet_plot}, on page
\pageref{fig:trend_tweet_plot}.

\begin{figure}[htb]
	\centering
    \includegraphics[width=\textwidth]{tweet_trend_plot.png}
    \label{fig:trend_tweet_plot}
    \caption{Tweet trend plot}
This is the Twitter trend plot. The plot show the moving average in the middle
and the Average directional graph at the bottom. Time frame: Apr 26 - May 26.

The blue line in the top part shows the moving average with 8 days as the
average time frame. The white line has a 3 day time frame.

The bottom part show three lines, red, green, and white. The red is reduction
in price. The green is increase in price. The white one is the ADX.
\end{figure}
%

\section{Discussion}\label{results:discussion}
We have satisfying and unsatisfying results. The
reasonable results should be expanded, retested and improved.
There are clear indications that dictionaries, automatically compiled
from a manually classified tweets, can be successfully used to classify
sentiment.

The accomplished research, based on the RQ, can be described
as satisfactory. We set out to investigate how we can determine the sentiment of
a tweet, \ref{introduction:rq1}, how Twitter can be used to aggregate a trend,
\ref{introduction:rq2}, and how Twitter based trends compare to the technical
analysis of stock markets, \ref{introduction:rq3}.

RQ1 more specifically aims at the information of tweets, the knowledge we
can extract from them, and classification of the sentiment of a tweet. By
creating dictionaries we extracted words from manually labeled tweets, giving us
a way to classify new tweets. We ended up only using the tweet text for
classification. Other metadata should have been explored. The best way of
classifying tweets we found to be the SVM classifier. We have gained new
knowledge in most aspects of RQ1.

RQ2 investigates the complicated part of aggregating a trend based on Twitter. This
turned out to be difficult. Mainly by the lack of good ideas of how we could do
it, but also the difficulty of transforming data to a usable format. In the end
we transformed tweet data to the same format as stock data and used that for
the trend aggregation.

RQ3 takes the trend a step further and compares technical analysis with the
Twitter based sentiment trend. After plotting MA and ADX for both finance and
Twitter data, we compared the graphs. The two plots
can be seen in figure \ref{fig:trend_finance_plot}, page
\pageref{fig:trend_finance_plot}, and figure \ref{fig:trend_finance_plot}, page
\pageref{fig:trend_finance_plot}. In the figures we looked for similarities.
For the MA we can argue that the blue lines, MA with 8
day intervals, are quite similar. We can make no definite conclusion
that the Twitter trend is representative for the finance market. Technical
analysis is still better, but sentiment analysis is a possibility.
The ADX show no similarities between the Twitter sentiment trend and the finance
trend.
%


text:
import resolveConfig from '../src/public/resolve-config'
import { createContext } from '../src/lib/setupContextUtils'
import bigSign from '../src/util/bigSign'

/**
 * This is a function that the prettier-plugin-tailwindcss would use. It would
 * do the actual sorting based on the classes and order we return from `getClassOrder`.
 *
 * This way the actual sorting logic is done in the plugin which allows you to
 * put unknown classes at the end for example.
 *
 * @param {Array<[string, bigint]>} arrayOfTuples
 * @returns {string}
 */
function defaultSort(arrayOfTuples) {
  return arrayOfTuples
    .sort(([, a], [, z]) => {
      if (a === z) return 0
      if (a === null) return -1
      if (z === null) return 1
      return bigSign(a - z)
    })
    .map(([className]) => className)
    .join(' ')
}

it('should return a list of tuples with the sort order', () => {
  let input = 'font-bold underline hover:font-medium unknown'
  let config = {}
  let context = createContext(resolveConfig(config))
  expect(context.getClassOrder(input.split(' '))).toEqual([
    ['font-bold', expect.any(BigInt)],
    ['underline', expect.any(BigInt)],
    ['hover:font-medium', expect.any(BigInt)],

    // Unknown values receive `null`
    ['unknown', null],
  ])
})

it.each([
  // Utitlies
  ['px-3 p-1 py-3', 'p-1 px-3 py-3'],

  // Utitlies and components
  ['px-4 container', 'container px-4'],

  // Utilities with variants
  ['px-3 focus:hover:p-3 hover:p-1 py-3', 'px-3 py-3 hover:p-1 focus:hover:p-3'],

  // Utitlies with important
  ['px-3 !py-4', 'px-3 !py-4'],
  ['!py-4 px-3', '!py-4 px-3'],

  // Components with variants
  ['hover:container container', 'container hover:container'],

  // Components and utilities with variants
  [
    'focus:hover:container hover:underline hover:container p-1',
    'p-1 hover:container hover:underline focus:hover:container',
  ],

  // Leave user css order alone, and move to the front
  ['b p-1 a', 'b a p-1'],
  ['hover:b focus:p-1 a', 'hover:b a focus:p-1'],

  // Add special treatment for `group` and `peer`
  ['a peer container underline', 'a peer container underline'],
])('should sort "%s" based on the order we generate them in to "%s"', (input, output) => {
  let config = {}
  let context = createContext(resolveConfig(config))
  expect(defaultSort(context.getClassOrder(input.split(' ')))).toEqual(output)
})

it.each([
  // Utitlies
  ['tw-px-3 tw-p-1 tw-py-3', 'tw-p-1 tw-px-3 tw-py-3'],

  // Utitlies and components
  ['tw-px-4 tw-container', 'tw-container tw-px-4'],

  // Utilities with variants
  [
    'tw-px-3 focus:hover:tw-p-3 hover:tw-p-1 tw-py-3',
    'tw-px-3 tw-py-3 hover:tw-p-1 focus:hover:tw-p-3',
  ],

  // Utitlies with important
  ['tw-px-3 !tw-py-4', 'tw-px-3 !tw-py-4'],
  ['!tw-py-4 tw-px-3', '!tw-py-4 tw-px-3'],

  // Components with variants
  ['hover:tw-container tw-container', 'tw-container hover:tw-container'],

  // Components and utilities with variants
  [
    'focus:hover:tw-container hover:tw-underline hover:tw-container tw-p-1',
    'tw-p-1 hover:tw-container hover:tw-underline focus:hover:tw-container',
  ],

  // Leave user css order alone, and move to the front
  ['b tw-p-1 a', 'b a tw-p-1'],
  ['hover:b focus:tw-p-1 a', 'hover:b a focus:tw-p-1'],

  // Add special treatment for `group` and `peer`
  ['a tw-peer tw-container tw-underline', 'a tw-peer tw-container tw-underline'],
])(
  'should sort "%s" with prefixex based on the order we generate them in to "%s"',
  (input, output) => {
    let config = { prefix: 'tw-' }
    let context = createContext(resolveConfig(config))
    expect(defaultSort(context.getClassOrder(input.split(' ')))).toEqual(output)
  }
)


text:
#include "themis/secure_message.h"

#include "themis/secure_keygen.h"
#include "themis/secure_message_wrapper.h"

static bool valid_private_key(const uint8_t* private_key, size_t private_key_length)
{
    if (themis_is_valid_asym_key(private_key, private_key_length) == THEMIS_SUCCESS) {
        themis_key_kind_t private_key_kind = themis_get_asym_key_kind(private_key, private_key_length);
        switch (private_key_kind) {
        case THEMIS_KEY_EC_PRIVATE:
        case THEMIS_KEY_RSA_PRIVATE:
            return true;
        default:
            break;
        }
    }
    return false;
}

static bool valid_public_key(const uint8_t* public_key, size_t public_key_length)
{
    if (themis_is_valid_asym_key(public_key, public_key_length) == THEMIS_SUCCESS) {
        themis_key_kind_t public_key_kind = themis_get_asym_key_kind(public_key, public_key_length);
        switch (public_key_kind) {
        case THEMIS_KEY_EC_PUBLIC:
        case THEMIS_KEY_RSA_PUBLIC:
            return true;
        default:
            break;
        }
    }
    return false;
}

static bool matching_key_kinds(const uint8_t* private_key,
                               size_t private_key_length,
                               const uint8_t* public_key,
                               size_t public_key_length)
{
    themis_key_kind_t private_key_kind = themis_get_asym_key_kind(private_key, private_key_length);
    themis_key_kind_t public_key_kind = themis_get_asym_key_kind(public_key, public_key_length);
    if (private_key_kind == THEMIS_KEY_EC_PRIVATE && public_key_kind == THEMIS_KEY_EC_PUBLIC) {
        return true;
    }
    if (private_key_kind == THEMIS_KEY_RSA_PRIVATE && public_key_kind == THEMIS_KEY_RSA_PUBLIC) {
        return true;
    }
    return false;
}

themis_status_t themis_secure_message_encrypt(const uint8_t* private_key,
                                              const size_t private_key_length,
                                              const uint8_t* public_key,
                                              const size_t public_key_length,
                                              const uint8_t* message,
                                              const size_t message_length,
                                              uint8_t* encrypted_message,
                                              size_t* encrypted_message_length)
{
    THEMIS_CHECK_PARAM(message != NULL);
    THEMIS_CHECK_PARAM(message_length != 0);
    THEMIS_CHECK_PARAM(encrypted_message_length != NULL);
    THEMIS_CHECK_PARAM(valid_private_key(private_key, private_key_length));
    THEMIS_CHECK_PARAM(valid_public_key(public_key, public_key_length));
    THEMIS_CHECK_PARAM(
        matching_key_kinds(private_key, private_key_length, public_key, public_key_length));

    themis_secure_message_encrypter_t* ctx = NULL;
    ctx = themis_secure_message_encrypter_init(private_key, private_key_length, public_key, public_key_length);
    THEMIS_CHECK_PARAM(ctx);

    themis_status_t status = themis_secure_message_encrypter_proceed(ctx,
                                                                     message,
                                                                     message_length,
                                                                     encrypted_message,
                                                                     encrypted_message_length);
    themis_secure_message_encrypter_destroy(ctx);
    return status;
}

themis_status_t themis_secure_message_decrypt(const uint8_t* private_key,
                                              const size_t private_key_length,
                                              const uint8_t* public_key,
                                              const size_t public_key_length,
                                              const uint8_t* encrypted_message,
                                              const size_t encrypted_message_length,
                                              uint8_t* message,
                                              size_t* message_length)
{
    THEMIS_CHECK_PARAM(encrypted_message != NULL);
    THEMIS_CHECK_PARAM(encrypted_message_length >= sizeof(themis_secure_message_hdr_t));
    THEMIS_CHECK_PARAM(message_length != NULL);
    THEMIS_CHECK_PARAM(valid_private_key(private_key, private_key_length));
    THEMIS_CHECK_PARAM(valid_public_key(public_key, public_key_length));
    THEMIS_CHECK_PARAM(
        matching_key_kinds(private_key, private_key_length, public_key, public_key_length));

    themis_secure_message_hdr_t* message_hdr = (themis_secure_message_hdr_t*)encrypted_message;
    THEMIS_CHECK_PARAM(IS_THEMIS_SECURE_MESSAGE_ENCRYPTED(message_hdr->message_type));

    themis_secure_message_decrypter_t* ctx = NULL;
    ctx = themis_secure_message_decrypter_init(private_key, private_key_length, public_key, public_key_length);
    THEMIS_CHECK_PARAM(ctx);

    themis_status_t status = themis_secure_message_decrypter_proceed(ctx,
                                                                     encrypted_message,
                                                                     encrypted_message_length,
                                                                     message,
                                                                     message_length);
    themis_secure_message_decrypter_destroy(ctx);
    return status;
}

themis_status_t themis_secure_message_sign(const uint8_t* private_key,
                                           const size_t private_key_length,
                                           const uint8_t* message,
                                           const size_t message_length,
                                           uint8_t* signed_message,
                                           size_t* signed_message_length)
{
    THEMIS_CHECK_PARAM(message != NULL);
    THEMIS_CHECK_PARAM(message_length != 0);
    THEMIS_CHECK_PARAM(signed_message_length != NULL);
    THEMIS_CHECK_PARAM(valid_private_key(private_key, private_key_length));

    themis_secure_message_signer_t* ctx = NULL;
    ctx = themis_secure_message_signer_init(private_key, private_key_length);
    THEMIS_CHECK_PARAM(ctx);

    themis_status_t res = themis_secure_message_signer_proceed(ctx,
                                                               message,
                                                               message_length,
                                                               signed_message,
                                                               signed_message_length);
    themis_secure_message_signer_destroy(ctx);
    return res;
}

themis_status_t themis_secure_message_verify(const uint8_t* public_key,
                                             const size_t public_key_length,
                                             const uint8_t* signed_message,
                                             const size_t signed_message_length,
                                             uint8_t* message,
                                             size_t* message_length)
{
    THEMIS_CHECK_PARAM(signed_message != NULL);
    THEMIS_CHECK_PARAM(signed_message_length >= sizeof(themis_secure_message_hdr_t));
    THEMIS_CHECK_PARAM(message_length != NULL);
    THEMIS_CHECK_PARAM(valid_public_key(public_key, public_key_length));

    themis_secure_message_hdr_t* message_hdr = (themis_secure_message_hdr_t*)signed_message;
    THEMIS_CHECK_PARAM(IS_THEMIS_SECURE_MESSAGE_SIGNED(message_hdr->message_type));

    themis_secure_message_verifier_t* ctx = NULL;
    ctx = themis_secure_message_verifier_init(public_key, public_key_length);
    THEMIS_CHECK_PARAM(ctx);

    themis_status_t status = themis_secure_message_verifier_proceed(ctx,
                                                                    signed_message,
                                                                    signed_message_length,
                                                                    message,
                                                                    message_length);
    themis_secure_message_verifier_destroy(ctx);
    return status;
}

/*
 * themis_secure_message_wrap() and themis_secure_message_unwrap() functions
 * are deprecated in favor of more specific themis_secure_message_encrypt()
 * themis_secure_message_decrypt(), themis_secure_message_sign(),
 * themis_secure_message_verify().
 *
 * The old functions combined the interface of the new ones (wrap = encrypt
 * or sign, unwrap = decrypt or verify). The new functions provide a more
 * cleanly separated interface for distinct concerns.
 *
 * Note that while their implementation looks similar, they are not quite
 * the same and differ slightly in error handling. Don't try to reimplement
 * them in terms of each other. We will remove wrap and unwrap eventually.
 */

themis_status_t themis_secure_message_wrap(const uint8_t* private_key,
                                           const size_t private_key_length,
                                           const uint8_t* public_key,
                                           const size_t public_key_length,
                                           const uint8_t* message,
                                           const size_t message_length,
                                           uint8_t* wrapped_message,
                                           size_t* wrapped_message_length)
{
    THEMIS_CHECK_PARAM(private_key != NULL);
    THEMIS_CHECK_PARAM(private_key_length != 0);
    THEMIS_CHECK_PARAM(message != NULL);
    THEMIS_CHECK_PARAM(message_length != 0);
    THEMIS_CHECK_PARAM(wrapped_message_length != NULL);
    if (public_key == NULL && public_key_length == 0) {
        themis_secure_message_signer_t* ctx = NULL;
        ctx = themis_secure_message_signer_init(private_key, private_key_length);
        THEMIS_CHECK(ctx != NULL);
        themis_status_t res = themis_secure_message_signer_proceed(ctx,
                                                                   message,
                                                                   message_length,
                                                                   wrapped_message,
                                                                   wrapped_message_length);
        themis_secure_message_signer_destroy(ctx);
        return res;
    }
    THEMIS_CHECK_PARAM(public_key != NULL);
    THEMIS_CHECK_PARAM(public_key_length != 0);
    themis_secure_message_encrypter_t* ctx = NULL;
    ctx = themis_secure_message_encrypter_init(private_key, private_key_length, public_key, public_key_length);
    THEMIS_CHECK__(ctx != NULL, return THEMIS_INVALID_PARAMETER);
    themis_status_t res = themis_secure_message_encrypter_proceed(ctx,
                                                                  message,
                                                                  message_length,
                                                                  wrapped_message,
                                                                  wrapped_message_length);
    themis_secure_message_encrypter_destroy(ctx);
    return res;

    return THEMIS_INVALID_PARAMETER;
}

themis_status_t themis_secure_message_unwrap(const uint8_t* private_key,
                                             const size_t private_key_length,
                                             const uint8_t* public_key,
                                             const size_t public_key_length,
                                             const uint8_t* wrapped_message,
                                             const size_t wrapped_message_length,
                                             uint8_t* message,
                                             size_t* message_length)
{
    THEMIS_CHECK_PARAM(public_key != NULL);
    THEMIS_CHECK_PARAM(public_key_length != 0);
    THEMIS_CHECK_PARAM(wrapped_message != NULL);
    THEMIS_CHECK_PARAM(wrapped_message_length >= sizeof(themis_secure_message_hdr_t));
    THEMIS_CHECK_PARAM(message_length != NULL);
    themis_secure_message_hdr_t* message_hdr = (themis_secure_message_hdr_t*)wrapped_message;
    THEMIS_CHECK_PARAM(IS_THEMIS_SECURE_MESSAGE_SIGNED(message_hdr->message_type)
                       || IS_THEMIS_SECURE_MESSAGE_ENCRYPTED(message_hdr->message_type));
    if (IS_THEMIS_SECURE_MESSAGE_SIGNED(message_hdr->message_type)) {
        themis_secure_message_verifier_t* ctx = NULL;
        ctx = themis_secure_message_verifier_init(public_key, public_key_length);
        THEMIS_CHECK(ctx != NULL);
        themis_status_t res = themis_secure_message_verifier_proceed(ctx,
                                                                     wrapped_message,
                                                                     wrapped_message_length,
                                                                     message,
                                                                     message_length);
        themis_secure_message_verifier_destroy(ctx);
        return res;
    }
    THEMIS_CHECK_PARAM(private_key != NULL);
    THEMIS_CHECK_PARAM(private_key_length != 0);
    themis_secure_message_decrypter_t* ctx = NULL;
    ctx = themis_secure_message_decrypter_init(private_key, private_key_length, public_key, public_key_length);
    THEMIS_CHECK__(ctx, return THEMIS_INVALID_PARAMETER);
    themis_status_t res = themis_secure_message_decrypter_proceed(ctx,
                                                                  wrapped_message,
                                                                  wrapped_message_length,
                                                                  message,
                                                                  message_length);
    themis_secure_message_decrypter_destroy(ctx);
    return res;

    return THEMIS_INVALID_PARAMETER;
}


text:
set -e

SCRIPT_NAME=$0

if [ "$#" -lt 2 ]; then
    echo "$SCRIPT_NAME [-w] <pdf1> <pdf2>"
    echo "  Pass -w to not fail if the rendering of the PDFs is different"
    exit 1
fi

command -v pdftoppm >/dev/null 2>&1 || { echo "$SCRIPT_NAME: pdftoppm required" >&2; exit 1; }

RENDER_WARNING=false
if [ "$1" = "-w" ]; then
    RENDER_WARNING=true
    shift
fi

PDF1=$1
PDF2=$2
PDFTOPPM="pdftoppm -aa no -aaVector no"

PDF1_PAGE_COUNT=$(pdfinfo $PDF1 | grep "Pages:")
PDF2_PAGE_COUNT=$(pdfinfo $PDF2 | grep "Pages:")

# Check the page count is the same
if [ "$PDF1_PAGE_COUNT" != "$PDF2_PAGE_COUNT" ]; then
    echo "$SCRIPT_NAME: different number of pages"
    echo "  pdf1 -> $PDF1_PAGE_COUNT"
    echo "  pdf2 -> $PDF2_PAGE_COUNT"
    exit 1
fi

# Check that the page size is the same
PDF1_PAGESIZE=$(pdfinfo $PDF1 | grep "Page size:")
PDF2_PAGESIZE=$(pdfinfo $PDF2 | grep "Page size:")
if [ "$PDF1_PAGESIZE" != "$PDF2_PAGESIZE" ]; then
    echo "$SCRIPT_NAME: Page sizes are different"
    echo "  pdf1 -> $PDF1_PAGESIZE"
    echo "  pdf2 -> $PDF2_PAGESIZE"
    exit 1
fi

# Create temporary folders since the rest of the comparisons
# require them.
rm -fr _pdf1 && mkdir _pdf1
rm -fr _pdf2 && mkdir _pdf2

# Check that the text in the PDFs is the same
pdftotext $PDF1 _pdf1/pdf1.txt
pdftotext $PDF2 _pdf2/pdf2.txt
if ! diff _pdf1/pdf1.txt _pdf2/pdf2.txt > /dev/null; then
    echo "$SCRIPT_NAME: found difference in the text in the PDFs"
    echo " See _pdf1/pdf1.txt and _pdf2/pdf2.txt"
    rm -fr _pdf*
    exit 1
fi
rm _pdf1/pdf1.txt _pdf2/pdf2.txt

# Check that the renderings of the PDFs are the same
$PDFTOPPM $PDF1 _pdf1/
$PDFTOPPM $PDF2 _pdf2/
if ! diff _pdf1 _pdf2 >/dev/null; then
    echo "$SCRIPT_NAME: found difference between page renderings"
    rm -fr _pdf*
    # Don't fail if render warnings are enabled
    $RENDER_WARNING || exit 1
fi

rm -fr _pdf*
exit 0


text:
---
uid: SolidEdgeAssembly.AssemblyCopy.AddNewComponentsOnUpdate
summary:
remarks:
---


text:
import {inspect} from 'util';

import defineClass from '../defineClass';

import ConnectionMerger from '../connection/ConnectionMerger';
import NodeConnectionMerger from '../connection/NodeConnectionMerger';

import assertSingleArgument from './assertSingleArgument';

function assertSource(source) {
  if (source == null || source.getNodeSource == null) {
    throw new Error(`${inspect(source)} is not a valid source node`);
  }
}

export default defineClass()
  .setOnceMandatoryProperty('_connectionSource', {title: 'Source'})
  .methods({
    fromSource(source) {
      assertSingleArgument(arguments.length);
      this._connectionSource =
        this._createMerger([source], {singleSource: true});
      return this;
    },

    fromSources(...sources) {
      return this._fromSourcesArray(sources);
    },

    fromSourcesWithMatchingPriorities(...sources) {
      return this._fromSourcesArray(sources, {prioritiesShouldMatch: true});
    },

    _fromSourcesArray(sources, {prioritiesShouldMatch = false} = {}) {
      this._connectionSource = this._createMerger(sources, {
        prioritiesShouldMatch,
        singleSource: false,
      });
      return this;
    },

    _createMerger(sources, opts) {
      sources.forEach(assertSource);
      return new ConnectionMerger(sources, this._direction, opts);
    },

    fromSourceNode(connectionSourceNode) {
      this._connectionSource =
        new NodeConnectionMerger(connectionSourceNode, this._direction);
      this._connectionSourceNode = connectionSourceNode;
      return this;
    },
  })
  .buildPrototype();


text:
package org.comicwiki.serializers;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;

public class YearDeserializer extends StdDeserializer<Date> {

	protected YearDeserializer() {
		super(Date.class);
	}

	/**
	 *
	 */
	private static final long serialVersionUID = -8998268740787798503L;

	@Override
	public Date deserialize(JsonParser p, DeserializationContext ctxt)
			throws IOException, JsonProcessingException {
		ObjectMapper mapper = (ObjectMapper) p.getCodec();
		JsonNode valueNode = mapper.readTree(p);
		String dateText = valueNode.asText();
		try {
			Date time = new SimpleDateFormat("yyyy").parse(dateText);
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(time);
			calendar.set(Calendar.ERA,
					(dateText.charAt(0) == '+') ? GregorianCalendar.AD
							: GregorianCalendar.BC);
			return calendar.getTime();
		} catch (ParseException e) {
			throw new IOException(e);
		}
	}

}


text:
function xmlhttpPost(strURL,formname,responsediv,responsemsg) {
    var xmlHttpReq = false;
    var self = this;
    // Xhr per Mozilla/Safari/Ie7
    if (window.XMLHttpRequest) {
        self.xmlHttpReq = new XMLHttpRequest();
    }
    // per tutte le altre versioni di IE
    else if (window.ActiveXObject) {
        self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
    }
    self.xmlHttpReq.open('POST', strURL, true);
    self.xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    self.xmlHttpReq.onreadystatechange = function() {
        if (self.xmlHttpReq.readyState == 4) {
			// Quando pronta, visualizzo la risposta del form
            updatepage(self.xmlHttpReq.responseText,responsediv);
        }
		else{
			// In attesa della risposta del form visualizzo il msg di attesa
			updatepage(responsemsg,responsediv);

		}
    }
    self.xmlHttpReq.send(getquerystring(formname));
}

function getquerystring(formname) {
    var form = document.forms[formname];
	var qstr = "";

    function GetElemValue(name, value) {
        qstr += (qstr.length > 0 ? "&" : "")
            + escape(name).replace(/\+/g, "%2B") + "="
            + escape(value ? value : "").replace(/\+/g, "%2B");
			//+ escape(value ? value : "").replace(/\n/g, "%0D");
    }

	var elemArray = form.elements;
    for (var i = 0; i < elemArray.length; i++) {
        var element = elemArray[i];
        var elemType = element.type.toUpperCase();
        var elemName = element.name;
        if (elemName) {
            if (elemType == "TEXT"
                    || elemType == "TEXTAREA"
                    || elemType == "PASSWORD"
					|| elemType == "BUTTON"
					|| elemType == "RESET"
					|| elemType == "SUBMIT"
					|| elemType == "FILE"
					|| elemType == "IMAGE"
                    || elemType == "HIDDEN")
                GetElemValue(elemName, element.value);
            else if (elemType == "CHECKBOX" && element.checked)
                GetElemValue(elemName,
                    element.value ? element.value : "On");
            else if (elemType == "RADIO" && element.checked)
                GetElemValue(elemName, element.value);
            else if (elemType.indexOf("SELECT") != -1)
                for (var j = 0; j < element.options.length; j++) {
                    var option = element.options[j];
                    if (option.selected)
                        GetElemValue(elemName,
                            option.value ? option.value : option.text);
                }
        }
    }
    return qstr;
}
function updatepage(str,responsediv){
    document.getElementById(responsediv).innerHTML = str;
}