text:
package gnu.xml.aelfred2;

import java.io.*;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Locale;
import java.util.Stack;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;

import org.xml.sax.*;
import org.xml.sax.ext.*;
import org.xml.sax.helpers.NamespaceSupport;

/**
 * An enhanced SAX2 version of Microstar's Ælfred XML parser.
 * The enhancements primarily relate to significant improvements in
 * conformance to the XML specification, and SAX2 support.  Performance
 * has been improved.  See the package level documentation for more
 * information.
 *
 *

 *

 *	Name
 *	Notes

 *
 *
Features ... URL prefix is
 * http://xml.org/sax/features/

 *
 *
(URL)/external-general-entities
 *	Value defaults to true

 *
(URL)/external-parameter-entities
 *	Value defaults to true

 *
(URL)/is-standalone
 *	(PRELIMINARY) Returns true iff the document's parsing
 *	has started (some non-error event after startDocument()
 *	was reported) and the document's standalone flag is set.

 *
(URL)/namespace-prefixes
 *	Value defaults to false (but XML 1.0 names are
 *		always reported)

 *
(URL)/lexical-handler/parameter-entities
 *	Value is fixed at true

 *
(URL)/namespaces
 *	Value defaults to true

 *
(URL)/resolve-dtd-uris
 *	(PRELIMINARY) Value defaults to true

 *
(URL)/string-interning
 *	Value is fixed at true

 *
(URL)/use-attributes2
 *	(PRELIMINARY) Value is fixed at true

 *
(URL)/use-entity-resolver2
 *	(PRELIMINARY) Value defaults to true

 *
(URL)/validation
 *	Value is fixed at false

 *
 *
Handler Properties ... URL prefix is
 * http://xml.org/sax/properties/

 *
 *
(URL)/declaration-handler
 *	A declaration handler may be provided.

 *
(URL)/lexical-handler
 *	A lexical handler may be provided.

 *

 *
 *
This parser currently implements the SAX1 Parser API, but
 * it may not continue to do so in the future.
 *
 * @author Written by David Megginson (version 1.2a from Microstar)
 * @author Updated by David Brownell <dbrownell@users.sourceforge.net>
 * @see org.xml.sax.Parser
 */
final public class SAXDriver
  implements Locator, Attributes2, XMLReader, Parser, AttributeList
{

  private final DefaultHandler2 base = new DefaultHandler2();
  private XmlParser parser;

  private EntityResolver entityResolver = base;
  private EntityResolver2 resolver2 = null;
  private ContentHandler contentHandler = base;
  private DTDHandler dtdHandler = base;
  private ErrorHandler errorHandler = base;
  private DeclHandler declHandler = base;
  private LexicalHandler lexicalHandler = base;

  private String elementName;
  private Stack entityStack;

  // one vector (of object/struct): faster, smaller
  private List attributesList;

  private boolean namespaces = true;
  private boolean xmlNames = false;
  private boolean extGE = true;
  private boolean extPE = true;
  private boolean resolveAll = true;
  private boolean useResolver2 = true;

  // package private to allow (read-only) access in XmlParser
  boolean stringInterning = true;

  private int attributeCount;
  private boolean attributes;
  private String[] nsTemp;
  private NamespaceSupport prefixStack;

  //
  // Constructor.
  //

  /**
   * Constructs a SAX Parser.
   */
  public SAXDriver()
  {
    reset();
  }

  private void reset()
  {
    elementName = null;
    entityStack = new Stack();
    attributesList = Collections.synchronizedList(new ArrayList());
    attributeCount = 0;
    attributes = false;
    nsTemp = new String[3];
    prefixStack = null;
  }

  //
  // Implementation of org.xml.sax.Parser.
  //

  /**
   * SAX1: Sets the locale used for diagnostics; currently,
   * only locales using the English language are supported.
   * @param locale The locale for which diagnostics will be generated
   */
  public void setLocale(Locale locale)
    throws SAXException
  {
    if ("en".equals(locale.getLanguage()))
      {
        return;
      }
    throw new SAXException ("AElfred2 only supports English locales.");
  }

  /**
   * SAX2: Returns the object used when resolving external
   * entities during parsing (both general and parameter entities).
   */
  public EntityResolver getEntityResolver()
  {
    return (entityResolver == base) ? null : entityResolver;
  }

  /**
   * SAX1, SAX2: Set the entity resolver for this parser.
   * @param handler The object to receive entity events.
   */
  public void setEntityResolver(EntityResolver resolver)
  {
    if (resolver instanceof EntityResolver2)
      {
        resolver2 = (EntityResolver2) resolver;
      }
    else
      {
        resolver2 = null;
      }
    if (resolver == null)
      {
        resolver = base;
      }
    entityResolver = resolver;
  }

  /**
   * SAX2: Returns the object used to process declarations related
   * to notations and unparsed entities.
   */
  public DTDHandler getDTDHandler()
  {
    return (dtdHandler == base) ? null : dtdHandler;
  }

  /**
   * SAX1, SAX2: Set the DTD handler for this parser.
   * @param handler The object to receive DTD events.
   */
  public void setDTDHandler(DTDHandler handler)
  {
    if (handler == null)
      {
        handler = base;
      }
    this.dtdHandler = handler;
  }

  /**
   * SAX1: Set the document handler for this parser.  If a
   * content handler was set, this document handler will supplant it.
   * The parser is set to report all XML 1.0 names rather than to
   * filter out "xmlns" attributes (the "namespace-prefixes" feature
   * is set to true).
   *
   * @deprecated SAX2 programs should use the XMLReader interface
   *  and a ContentHandler.
   *
   * @param handler The object to receive document events.
   */
  public void setDocumentHandler(DocumentHandler handler)
  {
    contentHandler = new Adapter(handler);
    xmlNames = true;
  }

  /**
   * SAX2: Returns the object used to report the logical
   * content of an XML document.
   */
  public ContentHandler getContentHandler()
  {
    return (contentHandler == base) ? null : contentHandler;
  }

  /**
   * SAX2: Assigns the object used to report the logical
   * content of an XML document.  If a document handler was set,
   * this content handler will supplant it (but XML 1.0 style name
   * reporting may remain enabled).
   */
  public void setContentHandler(ContentHandler handler)
  {
    if (handler == null)
      {
        handler = base;
      }
    contentHandler = handler;
  }

  /**
   * SAX1, SAX2: Set the error handler for this parser.
   * @param handler The object to receive error events.
   */
  public void setErrorHandler(ErrorHandler handler)
  {
    if (handler == null)
      {
        handler = base;
      }
    this.errorHandler = handler;
  }

  /**
   * SAX2: Returns the object used to receive callbacks for XML
   * errors of all levels (fatal, nonfatal, warning); this is never null;
   */
  public ErrorHandler getErrorHandler()
  {
    return (errorHandler == base) ? null : errorHandler;
  }

  /**
   * SAX1, SAX2: Auxiliary API to parse an XML document, used mostly
   * when no URI is available.
   * If you want anything useful to happen, you should set
   * at least one type of handler.
   * @param source The XML input source.  Don't set 'encoding' unless
   *  you know for a fact that it's correct.
   * @see #setEntityResolver
   * @see #setDTDHandler
   * @see #setContentHandler
   * @see #setErrorHandler
   * @exception SAXException The handlers may throw any SAXException,
   *  and the parser normally throws SAXParseException objects.
   * @exception IOException IOExceptions are normally through through
   *  the parser if there are problems reading the source document.
   */
  public void parse(InputSource source)
    throws SAXException, IOException
  {
    synchronized (base)
      {
        parser = new XmlParser();
        if (namespaces)
          {
            prefixStack = new NamespaceSupport();
          }
        else if (!xmlNames)
          {
            throw new IllegalStateException();
          }
        parser.setHandler(this);

        try
          {
            Reader r = source.getCharacterStream();
            InputStream in = source.getByteStream();

            parser.doParse(source.getSystemId(),
                           source.getPublicId(),
                           r,
                           in,
                           source.getEncoding());
          }
        catch (SAXException e)
          {
            throw e;
          }
        catch (IOException e)
          {
            throw e;
          }
        catch (RuntimeException e)
          {
            throw e;
          }
        catch (Exception e)
          {
            throw new SAXParseException(e.getMessage(), this, e);
          }
        finally
          {
            contentHandler.endDocument();
            reset();
          }
      }
  }

  /**
   * SAX1, SAX2: Preferred API to parse an XML document, using a
   * system identifier (URI).
   */
  public void parse(String systemId)
    throws SAXException, IOException
  {
    parse(new InputSource(systemId));
  }

  //
  // Implementation of SAX2 "XMLReader" interface
  //
  static final String FEATURE = "http://xml.org/sax/features/";
  static final String PROPERTY = "http://xml.org/sax/properties/";

  /**
   * SAX2: Tells the value of the specified feature flag.
   *
   * @exception SAXNotRecognizedException thrown if the feature flag
   *  is neither built in, nor yet assigned.
   */
  public boolean getFeature(String featureId)
    throws SAXNotRecognizedException, SAXNotSupportedException
  {
    if ((FEATURE + "validation").equals(featureId))
      {
        return false;
      }

    // external entities (both types) are optionally included
    if ((FEATURE + "external-general-entities").equals(featureId))
      {
        return extGE;
      }
    if ((FEATURE + "external-parameter-entities").equals(featureId))
      {
        return extPE;
      }

    // element/attribute names are as written in document; no mangling
    if ((FEATURE + "namespace-prefixes").equals(featureId))
      {
        return xmlNames;
      }

    // report element/attribute namespaces?
    if ((FEATURE + "namespaces").equals(featureId))
      {
        return namespaces;
      }

    // all PEs and GEs are reported
    if ((FEATURE + "lexical-handler/parameter-entities").equals(featureId))
      {
        return true;
      }

    // default is true
    if ((FEATURE + "string-interning").equals(featureId))
      {
        return stringInterning;
      }

    // EXTENSIONS 1.1

    // always returns isSpecified info
    if ((FEATURE + "use-attributes2").equals(featureId))
      {
        return true;
      }

    // meaningful between startDocument/endDocument
    if ((FEATURE + "is-standalone").equals(featureId))
      {
        if (parser == null)
          {
            throw new SAXNotSupportedException(featureId);
          }
        return parser.isStandalone();
      }

    // optionally don't absolutize URIs in declarations
    if ((FEATURE + "resolve-dtd-uris").equals(featureId))
      {
        return resolveAll;
      }

    // optionally use resolver2 interface methods, if possible
    if ((FEATURE + "use-entity-resolver2").equals(featureId))
      {
        return useResolver2;
      }

    throw new SAXNotRecognizedException(featureId);
  }

  // package private
  DeclHandler getDeclHandler()
  {
    return declHandler;
  }

  // package private
  boolean resolveURIs()
  {
    return resolveAll;
  }

  /**
   * SAX2:  Returns the specified property.
   *
   * @exception SAXNotRecognizedException thrown if the property value
   *  is neither built in, nor yet stored.
   */
  public Object getProperty(String propertyId)
    throws SAXNotRecognizedException
  {
    if ((PROPERTY + "declaration-handler").equals(propertyId))
      {
        return (declHandler == base) ? null : declHandler;
      }

    if ((PROPERTY + "lexical-handler").equals(propertyId))
      {
        return (lexicalHandler == base) ? null : lexicalHandler;
      }

    // unknown properties
    throw new SAXNotRecognizedException(propertyId);
  }

  /**
   * SAX2:  Sets the state of feature flags in this parser.  Some
   * built-in feature flags are mutable.
   */
  public void setFeature(String featureId, boolean value)
    throws SAXNotRecognizedException, SAXNotSupportedException
  {
    boolean state;

    // Features with a defined value, we just change it if we can.
    state = getFeature (featureId);

    if (state == value)
      {
        return;
      }
    if (parser != null)
      {
        throw new SAXNotSupportedException("not while parsing");
      }

    if ((FEATURE + "namespace-prefixes").equals(featureId))
      {
        // in this implementation, this only affects xmlns reporting
        xmlNames = value;
        // forcibly prevent illegal parser state
        if (!xmlNames)
          {
            namespaces = true;
          }
        return;
      }

    if ((FEATURE + "namespaces").equals(featureId))
      {
        namespaces = value;
        // forcibly prevent illegal parser state
        if (!namespaces)
          {
            xmlNames = true;
          }
        return;
      }

    if ((FEATURE + "external-general-entities").equals(featureId))
      {
        extGE = value;
        return;
      }
    if ((FEATURE + "external-parameter-entities").equals(featureId))
      {
        extPE = value;
        return;
      }
    if ((FEATURE + "resolve-dtd-uris").equals(featureId))
      {
        resolveAll = value;
        return;
      }

    if ((FEATURE + "use-entity-resolver2").equals(featureId))
      {
        useResolver2 = value;
        return;
      }

    throw new SAXNotRecognizedException(featureId);
  }

  /**
   * SAX2:  Assigns the specified property.  Like SAX1 handlers,
   * these may be changed at any time.
   */
  public void setProperty(String propertyId, Object value)
    throws SAXNotRecognizedException, SAXNotSupportedException
  {
    // see if the property is recognized
    getProperty(propertyId);

    // Properties with a defined value, we just change it if we can.

    if ((PROPERTY + "declaration-handler").equals(propertyId))
      {
        if (value == null)
          {
            declHandler = base;
          }
        else if (!(value instanceof DeclHandler))
          {
            throw new SAXNotSupportedException(propertyId);
          }
        else
          {
            declHandler = (DeclHandler) value;
          }
        return ;
      }

    if ((PROPERTY + "lexical-handler").equals(propertyId))
      {
        if (value == null)
          {
            lexicalHandler = base;
          }
        else if (!(value instanceof LexicalHandler))
          {
            throw new SAXNotSupportedException(propertyId);
          }
        else
          {
            lexicalHandler = (LexicalHandler) value;
          }
        return;
      }

    throw new SAXNotSupportedException(propertyId);
  }

  //
  // This is where the driver receives XmlParser callbacks and translates
  // them into SAX callbacks.  Some more callbacks have been added for
  // SAX2 support.
  //

  void startDocument()
    throws SAXException
  {
    contentHandler.setDocumentLocator(this);
    contentHandler.startDocument();
    attributesList.clear();
  }

  void skippedEntity(String name)
    throws SAXException
  {
    contentHandler.skippedEntity(name);
  }

  InputSource getExternalSubset(String name, String baseURI)
    throws SAXException, IOException
  {
    if (resolver2 == null || !useResolver2 || !extPE)
      {
        return null;
      }
    return resolver2.getExternalSubset(name, baseURI);
  }

  InputSource resolveEntity(boolean isPE, String name,
                            InputSource in, String baseURI)
    throws SAXException, IOException
  {
    InputSource  source;

    // external entities might be skipped
    if (isPE && !extPE)
      {
        return null;
      }
    if (!isPE && !extGE)
      {
        return null;
      }

    // ... or not
    lexicalHandler.startEntity(name);
    if (resolver2 != null && useResolver2)
      {
        source = resolver2.resolveEntity(name, in.getPublicId(),
                                         baseURI, in.getSystemId());
        if (source == null)
          {
            in.setSystemId(absolutize(baseURI,
                                      in.getSystemId(), false));
            source = in;
          }
      }
    else
      {
        in.setSystemId(absolutize(baseURI,
                                  in.getSystemId(),
                                  entityResolver != base));
        source = entityResolver.resolveEntity(in.getPublicId(),
                                              in.getSystemId());
        if (source == null)
          {
            source = in;
          }
      }
    startExternalEntity(name, source.getSystemId(), true);
    return source;
  }

  // absolutize a system ID relative to the specified base URI
  // (temporarily) package-visible for external entity decls
  String absolutize(String baseURI, String systemId, boolean nice)
    throws MalformedURLException, SAXException
  {
    // FIXME normalize system IDs -- when?
    // - Convert to UTF-8
    // - Map reserved and non-ASCII characters to %HH

    try
      {
        if (baseURI == null)
          {
            if (XmlParser.uriWarnings)
              {
                warn ("No base URI; hope this SYSTEM id is absolute: "
                      + systemId);
              }
            return new URL(systemId).toString();
          }
        else
          {
            return new URL(new URL(baseURI), systemId).toString();
          }
      }
    catch (MalformedURLException e)
      {
        // Let unknown URI schemes pass through unless we need
        // the JVM to map them to i/o streams for us...
        if (!nice)
          {
            throw e;
          }

        // sometimes sysids for notations or unparsed entities
        // aren't really URIs...
        warn("Can't absolutize SYSTEM id: " + e.getMessage());
        return systemId;
      }
  }

  void startExternalEntity(String name, String systemId, boolean stackOnly)
    throws SAXException
  {
    // The following warning was deleted because the application has the
    // option of not setting systemId. Sun's JAXP or Xerces seems to
    // ignore this case.
    /*
       if (systemId == null)
       warn ("URI was not reported to parser for entity " + name);
     */
    if (!stackOnly)  // spliced [dtd] needs startEntity
      {
        lexicalHandler.startEntity(name);
      }
    entityStack.push(systemId);
  }

  void endExternalEntity(String name)
    throws SAXException
  {
    if (!"[document]".equals(name))
      {
        lexicalHandler.endEntity(name);
      }
    entityStack.pop();
  }

  void startInternalEntity(String name)
    throws SAXException
  {
    lexicalHandler.startEntity(name);
  }

  void endInternalEntity(String name)
    throws SAXException
  {
    lexicalHandler.endEntity(name);
  }

  void doctypeDecl(String name, String publicId, String systemId)
    throws SAXException
  {
    lexicalHandler.startDTD(name, publicId, systemId);

    // ... the "name" is a declaration and should be given
    // to the DeclHandler (but sax2 doesn't).

    // the IDs for the external subset are lexical details,
    // as are the contents of the internal subset; but sax2
    // doesn't provide the internal subset "pre-parse"
  }

  void notationDecl(String name, String publicId, String systemId,
                    String baseUri)
    throws SAXException
  {
    try
      {
        dtdHandler.notationDecl(name, publicId,
                                (resolveAll && systemId != null)
                                ? absolutize(baseUri, systemId, true)
                                : systemId);
      }
    catch (IOException e)
      {
        // "can't happen"
        throw new SAXParseException(e.getMessage(), this, e);
      }
  }

  void unparsedEntityDecl(String name, String publicId, String systemId,
                          String baseUri, String notation)
    throws SAXException
  {
    try
      {
        dtdHandler.unparsedEntityDecl(name, publicId,
                                      resolveAll
                                      ? absolutize(baseUri, systemId, true)
                                      : systemId,
                                      notation);
      }
    catch (IOException e)
      {
        // "can't happen"
        throw new SAXParseException(e.getMessage(), this, e);
      }
  }

  void endDoctype()
    throws SAXException
  {
    lexicalHandler.endDTD();
  }

  private void declarePrefix(String prefix, String uri)
    throws SAXException
  {
    int index = uri.indexOf(':');

    // many versions of nwalsh docbook stylesheets
    // have bogus URLs; so this can't be an error...
    if (index < 1 && uri.length() != 0)
      {
        warn("relative URI for namespace: " + uri);
      }

    // FIXME:  char [0] must be ascii alpha; chars [1..index]
    // must be ascii alphanumeric or in "+-." [RFC 2396]

    //Namespace Constraints
    //name for xml prefix must be http://www.w3.org/XML/1998/namespace
    boolean prefixEquality = prefix.equals("xml");
    boolean uriEquality = uri.equals("http://www.w3.org/XML/1998/namespace");
    if ((prefixEquality || uriEquality) && !(prefixEquality && uriEquality))
      {
        fatal("xml is by definition bound to the namespace name " +
              "http://www.w3.org/XML/1998/namespace");
      }

    //xmlns prefix declaration is illegal but xml prefix declaration is llegal...
    if (prefixEquality && uriEquality)
      {
        return;
      }

    //name for xmlns prefix must be http://www.w3.org/2000/xmlns/
    prefixEquality = prefix.equals("xmlns");
    uriEquality = uri.equals("http://www.w3.org/2000/xmlns/");
    if ((prefixEquality || uriEquality) && !(prefixEquality && uriEquality))
      {
        fatal("http://www.w3.org/2000/xmlns/ is by definition bound" +
              " to prefix xmlns");
      }

    //even if the uri is http://www.w3.org/2000/xmlns/
    // it is illegal to declare it
    if (prefixEquality && uriEquality)
      {
        fatal ("declaring the xmlns prefix is illegal");
      }

    uri = uri.intern();
    prefixStack.declarePrefix(prefix, uri);
    contentHandler.startPrefixMapping(prefix, uri);
  }

  void attribute(String qname, String value, boolean isSpecified)
    throws SAXException
  {
    if (!attributes)
      {
        attributes = true;
        if (namespaces)
          {
            prefixStack.pushContext();
          }
      }

    // process namespace decls immediately;
    // then maybe forget this as an attribute
    if (namespaces)
      {
        int index;

        // default NS declaration?
        if (stringInterning)
          {
            if ("xmlns" == qname)
              {
                declarePrefix("", value);
                if (!xmlNames)
                  {
                    return;
                  }
              }
            // NS prefix declaration?
            else if ((index = qname.indexOf(':')) == 5
                     && qname.startsWith("xmlns"))
              {
                String prefix = qname.substring(6);

                if (prefix.equals(""))
                  {
                    fatal("missing prefix " +
                          "in namespace declaration attribute");
                  }
                if (value.length() == 0)
                  {
                    verror("missing URI in namespace declaration attribute: "
                           + qname);
                  }
                else
                  {
                    declarePrefix(prefix, value);
                  }
                if (!xmlNames)
                  {
                    return;
                  }
              }
          }
        else
          {
            if ("xmlns".equals(qname))
              {
                declarePrefix("", value);
                if (!xmlNames)
                  {
                    return;
                  }
              }
            // NS prefix declaration?
            else if ((index = qname.indexOf(':')) == 5
                     && qname.startsWith("xmlns"))
              {
                String prefix = qname.substring(6);

                if (value.length() == 0)
                  {
                    verror("missing URI in namespace decl attribute: "
                           + qname);
                  }
                else
                  {
                    declarePrefix(prefix, value);
                  }
                if (!xmlNames)
                  {
                    return;
                  }
              }
          }
      }
    // remember this attribute ...
    attributeCount++;

    // attribute type comes from querying parser's DTD records
    attributesList.add(new Attribute(qname, value, isSpecified));

  }

  void startElement(String elname)
    throws SAXException
  {
    ContentHandler handler = contentHandler;

    //
    // NOTE:  this implementation of namespace support adds something
    // like six percent to parsing CPU time, in a large (~50 MB)
    // document that doesn't use namespaces at all.  (Measured by PC
    // sampling, with a bug where endElement processing was omitted.)
    // [Measurement referred to older implementation, older JVM ...]
    //
    // It ought to become notably faster in such cases.  Most
    // costs are the prefix stack calling Hashtable.get() (2%),
    // String.hashCode() (1.5%) and about 1.3% each for pushing
    // the context, and two chunks of name processing.
    //

    if (!attributes)
      {
        if (namespaces)
          {
            prefixStack.pushContext();
          }
      }
    else if (namespaces)
      {

        // now we can patch up namespace refs; we saw all the
        // declarations, so now we'll do the Right Thing
        Iterator itt = attributesList.iterator();
        while (itt.hasNext())
          {
            Attribute attribute = (Attribute) itt.next();
            String qname = attribute.name;
            int index;

            // default NS declaration?
            if (stringInterning)
              {
                if ("xmlns" == qname)
                  {
                    continue;
                  }
              }
            else
              {
                if ("xmlns".equals(qname))
                  {
                    continue;
                  }
              }
            //Illegal in the new Namespaces Draft
            //should it be only in 1.1 docs??
            if (qname.equals (":"))
              {
                fatal("namespace names consisting of a single colon " +
                      "character are invalid");
              }
            index = qname.indexOf(':');

            // NS prefix declaration?
            if (index == 5 && qname.startsWith("xmlns"))
              {
                continue;
              }

            // it's not a NS decl; patch namespace info items
            if (prefixStack.processName(qname, nsTemp, true) == null)
              {
                fatal("undeclared attribute prefix in: " + qname);
              }
            else
              {
                attribute.nameSpace = nsTemp[0];
                attribute.localName = nsTemp[1];
              }
          }
      }

    // save element name so attribute callbacks work
    elementName = elname;
    if (namespaces)
      {
        if (prefixStack.processName(elname, nsTemp, false) == null)
          {
            fatal("undeclared element prefix in: " + elname);
            nsTemp[0] = nsTemp[1] = "";
          }
        handler.startElement(nsTemp[0], nsTemp[1], elname, this);
      }
    else
      {
        handler.startElement("", "", elname, this);
      }
    // elementName = null;

    // elements with no attributes are pretty common!
    if (attributes)
      {
        attributesList.clear();
        attributeCount = 0;
        attributes = false;
      }
  }

  void endElement(String elname)
    throws SAXException
  {
    ContentHandler handler = contentHandler;

    if (!namespaces)
      {
        handler.endElement("", "", elname);
        return;
      }
    prefixStack.processName(elname, nsTemp, false);
    handler.endElement(nsTemp[0], nsTemp[1], elname);

    Enumeration prefixes = prefixStack.getDeclaredPrefixes();

    while (prefixes.hasMoreElements())
      {
        handler.endPrefixMapping((String) prefixes.nextElement());
      }
    prefixStack.popContext();
  }

  void startCDATA()
    throws SAXException
  {
    lexicalHandler.startCDATA();
  }

  void charData(char[] ch, int start, int length)
    throws SAXException
  {
    contentHandler.characters(ch, start, length);
  }

  void endCDATA()
    throws SAXException
  {
    lexicalHandler.endCDATA();
  }

  void ignorableWhitespace(char[] ch, int start, int length)
    throws SAXException
  {
    contentHandler.ignorableWhitespace(ch, start, length);
  }

  void processingInstruction(String target, String data)
    throws SAXException
  {
    contentHandler.processingInstruction(target, data);
  }

  void comment(char[] ch, int start, int length)
    throws SAXException
  {
    if (lexicalHandler != base)
      {
        lexicalHandler.comment(ch, start, length);
      }
  }

  void fatal(String message)
    throws SAXException
  {
    SAXParseException fatal;

    fatal = new SAXParseException(message, this);
    errorHandler.fatalError(fatal);

    // Even if the application can continue ... we can't!
    throw fatal;
  }

  // We can safely report a few validity errors that
  // make layered SAX2 DTD validation more conformant
  void verror(String message)
    throws SAXException
  {
    SAXParseException err;

    err = new SAXParseException(message, this);
    errorHandler.error(err);
  }

  void warn(String message)
    throws SAXException
  {
    SAXParseException err;

    err = new SAXParseException(message, this);
    errorHandler.warning(err);
  }

  //
  // Implementation of org.xml.sax.Attributes.
  //

  /**
   * SAX1 AttributeList, SAX2 Attributes method
   * (don't invoke on parser);
   */
  public int getLength()
  {
    return attributesList.size();
  }

  /**
   * SAX2 Attributes method (don't invoke on parser);
   */
  public String getURI(int index)
  {
    if (index < 0 || index >= attributesList.size())
      {
        return null;
      }
    return ((Attribute) attributesList.get(index)).nameSpace;
  }

  /**
   * SAX2 Attributes method (don't invoke on parser);
   */
  public String getLocalName(int index)
  {
    if (index < 0 || index >= attributesList.size())
      {
        return null;
      }
    Attribute attr = (Attribute) attributesList.get(index);
    // FIXME attr.localName is sometimes null, why?
    if (namespaces && attr.localName == null)
      {
        // XXX fix this here for now
        int ci = attr.name.indexOf(':');
        attr.localName = (ci == -1) ? attr.name :
          attr.name.substring(ci + 1);
      }
    return (attr.localName == null) ? "" : attr.localName;
  }

  /**
   * SAX2 Attributes method (don't invoke on parser);
   */
  public String getQName(int index)
  {
    if (index < 0 || index >= attributesList.size())
      {
      return null;
      }
    Attribute attr = (Attribute) attributesList.get(index);
    return (attr.name == null) ? "" : attr.name;
  }

  /**
   * SAX1 AttributeList method (don't invoke on parser);
   */
  public String getName(int index)
  {
    return getQName(index);
  }

  /**
   * SAX1 AttributeList, SAX2 Attributes method
   * (don't invoke on parser);
   */
  public String getType(int index)
  {
    if (index < 0 || index >= attributesList.size())
      {
        return null;
      }
    String type = parser.getAttributeType(elementName, getQName(index));
    if (type == null)
      {
        return "CDATA";
      }
    // ... use DeclHandler.attributeDecl to see enumerations
    if (type == "ENUMERATION")
      {
        return "NMTOKEN";
      }
    return type;
  }

  /**
   * SAX1 AttributeList, SAX2 Attributes method
   * (don't invoke on parser);
   */
  public String getValue(int index)
  {
    if (index < 0 || index >= attributesList.size())
      {
        return null;
      }
    return ((Attribute) attributesList.get(index)).value;
  }

  /**
   * SAX2 Attributes method (don't invoke on parser);
   */
  public int getIndex(String uri, String local)
    {
      int length = getLength();

      for (int i = 0; i < length; i++)
        {
          if (!getURI(i).equals(uri))
            {
              continue;
            }
          if (getLocalName(i).equals(local))
            {
              return i;
            }
        }
      return -1;
  }

  /**
   * SAX2 Attributes method (don't invoke on parser);
   */
  public int getIndex(String xmlName)
  {
    int length = getLength();

    for (int i = 0; i < length; i++)
      {
        if (getQName(i).equals(xmlName))
          {
            return i;
          }
      }
    return -1;
  }

  /**
   * SAX2 Attributes method (don't invoke on parser);
   */
  public String getType(String uri, String local)
  {
    int index = getIndex(uri, local);

    if (index < 0)
      {
        return null;
      }
    return getType(index);
  }

  /**
   * SAX1 AttributeList, SAX2 Attributes method
   * (don't invoke on parser);
   */
  public String getType(String xmlName)
  {
    int index = getIndex(xmlName);

    if (index < 0)
      {
        return null;
      }
    return getType(index);
  }

  /**
   * SAX Attributes method (don't invoke on parser);
   */
  public String getValue(String uri, String local)
  {
    int index = getIndex(uri, local);

    if (index < 0)
      {
        return null;
      }
    return getValue(index);
  }

  /**
   * SAX1 AttributeList, SAX2 Attributes method
   * (don't invoke on parser);
   */
  public String getValue(String xmlName)
  {
    int index = getIndex(xmlName);

    if (index < 0)
      {
        return null;
      }
    return getValue(index);
  }

  //
  // Implementation of org.xml.sax.ext.Attributes2
  //

  /** @return false unless the attribute was declared in the DTD.
   * @throws java.lang.ArrayIndexOutOfBoundsException
   *   When the supplied index does not identify an attribute.
   */
  public boolean isDeclared(int index)
  {
    if (index < 0 || index >= attributeCount)
      {
        throw new ArrayIndexOutOfBoundsException();
      }
    String type = parser.getAttributeType(elementName, getQName(index));
    return (type != null);
  }

  /** @return false unless the attribute was declared in the DTD.
   * @throws java.lang.IllegalArgumentException
   *   When the supplied names do not identify an attribute.
   */
  public boolean isDeclared(String qName)
  {
    int index = getIndex(qName);
    if (index < 0)
      {
        throw new IllegalArgumentException();
      }
    String type = parser.getAttributeType(elementName, qName);
    return (type != null);
  }

  /** @return false unless the attribute was declared in the DTD.
   * @throws java.lang.IllegalArgumentException
   *   When the supplied names do not identify an attribute.
   */
  public boolean isDeclared(String uri, String localName)
  {
    int index = getIndex(uri, localName);
    return isDeclared(index);
  }

  /**
   * SAX-ext Attributes2 method (don't invoke on parser);
   */
  public boolean isSpecified(int index)
  {
    return ((Attribute) attributesList.get(index)).specified;
  }

  /**
   * SAX-ext Attributes2 method (don't invoke on parser);
   */
  public boolean isSpecified(String uri, String local)
  {
    int index = getIndex (uri, local);
    return isSpecified(index);
  }

  /**
   * SAX-ext Attributes2 method (don't invoke on parser);
   */
  public boolean isSpecified(String xmlName)
  {
    int index = getIndex (xmlName);
    return isSpecified(index);
  }

  //
  // Implementation of org.xml.sax.Locator.
  //

  /**
   * SAX Locator method (don't invoke on parser);
   */
  public String getPublicId()
  {
    return null;   // FIXME track public IDs too
  }

  /**
   * SAX Locator method (don't invoke on parser);
   */
  public String getSystemId()
  {
    if (entityStack.empty())
      {
        return null;
      }
    else
      {
        return (String) entityStack.peek();
      }
  }

  /**
   * SAX Locator method (don't invoke on parser);
   */
  public int getLineNumber()
  {
    return parser.getLineNumber();
  }

  /**
   * SAX Locator method (don't invoke on parser);
   */
  public int getColumnNumber()
  {
    return parser.getColumnNumber();
  }

  // adapter between SAX2 content handler and SAX1 document handler callbacks
  private static class Adapter
    implements ContentHandler
  {

    private DocumentHandler docHandler;

    Adapter(DocumentHandler dh)
    {
      docHandler = dh;
    }

    public void setDocumentLocator(Locator l)
    {
      docHandler.setDocumentLocator(l);
    }

    public void startDocument()
      throws SAXException
    {
      docHandler.startDocument();
    }

    public void processingInstruction(String target, String data)
      throws SAXException
    {
      docHandler.processingInstruction(target, data);
    }

    public void startPrefixMapping(String prefix, String uri)
    {
      /* ignored */
    }

    public void startElement(String namespace,
                             String local,
                             String name,
                             Attributes attrs)
      throws SAXException
    {
      docHandler.startElement(name, (AttributeList) attrs);
    }

    public void characters(char[] buf, int offset, int len)
      throws SAXException
    {
      docHandler.characters(buf, offset, len);
    }

    public void ignorableWhitespace(char[] buf, int offset, int len)
      throws SAXException
    {
      docHandler.ignorableWhitespace(buf, offset, len);
    }

    public void skippedEntity(String name)
    {
      /* ignored */
    }

    public void endElement(String u, String l, String name)
      throws SAXException
    {
      docHandler.endElement(name);
    }

    public void endPrefixMapping(String prefix)
    {
      /* ignored */
    }

    public void endDocument()
      throws SAXException
    {
      docHandler.endDocument();
    }
  }

  private static class Attribute
  {

    String name;
    String value;
    String nameSpace;
    String localName;
    boolean specified;

    Attribute(String name, String value, boolean specified)
    {
      this.name = name;
      this.value = value;
      this.nameSpace = "";
      this.specified = specified;
    }

  }

}


The Smithsonian Institution's Cooper-Hewitt National Design Museum (CHNDM) was renovating its "Miller/Fox" building completely. The Miller/Fox building is part of the CHNDM located at 2 E. 91st St, New York City, New York. Originally a two 5-story townhome facing E. 90th St, constructed in the late 1800 & early 1900's, they were purchased by the Smithsonian Institution (SI) and connected to each other and to the Carnegie Mansion building in the 1990's. The 37,000 SF building was used to store the museum's extensive collection of design objects. The purpose of renovation was to relocate most of the administrative functions and the design library, located in the Mansion into the renovated Miller/Fox building.
Work under this project included hazardous material abatement, structural upgrades of the first two Floors, and architectural, mechanical, electrical, fire protection, and security renovations to accommodate the building's new functions. The Project was designed to be constructed for a rating of Silver in accordance with LEED-NC version 2.2.
The historic restoration work included repair, restore existing ceiling décor with moldings, hardwood floor, marble fire places, existing wood windows and wall finishes.


text:
Home / CBD Vape Blog / Is Vaping Safe as Opposed to Smoking Cigarettes?
Is Vaping Safe as Opposed to Smoking?
Vaping has always been a subject of controversy. Some argue that it's harmless since "you just inhale water vapour," but others say that "it's pure cancer!" and you shouldn't try it even once. Who's right? What should you believe? Read on to find out everything you need to know about vaping, vaping health, and vaping safety.
History of Vaping
In the 1950s, doctors began to voice concerns about how smoking cigarettes was harming people's health: lip cancer, lung cancer, and heart disease were only a few of the most health issues among heavy smokers. The list grew until it contained a host of conditions that affect almost every organ in the body.
Over the years, many inventors came up with various ways to replace cigarettes. In 2003, a Chinese inventor called Hon Lik created e-cigarettes as a safer alternative to deliver nicotine.
A year after he conceived of the idea, his employer released the product in the Chinese market and eventually reached the US in 2007.
What Is Vaping?
Simply put, vaping refers to using a device that heats a liquid so that the actual vapour is inhaled. The process looks very similar to smoking cigarettes, but there's no tobacco involved.
The vaping liquid is usually a mixture of propylene glycol, vegetable glycerin, flavours, and optional nicotine. The dose of each ingredient, including nicotine, can be regulated to contain more or less vapour and cause different sensations. For example, more vegetable glycerin creates more vapour.
Flavours are there to make the experience more personalized and pleasant to each user. Usually, people who switch from smoking cigarettes to vaping need a dose of nicotine. Even those who start smoking with vapes still prefer using nicotine.
The vaping device is called an e-cigarette. As the name suggests, it's an electronic device. There are many types of e-cigarettes.
Types of E-cigarettes
Cigalike - compact and small, are ideal for anyone who is just discovering the world of vaping or looking for a way to reduce or quit smoking. This type of e-cigarette replicates a real tobacco cigarette in size and style.
Pen kits can vary in both size and power output. They can have an external or internal battery. Can be used to vape as mouth-to-lung (MTL), or direct-to-lung (DTL) sub-ohm style. Almost all types of e-liquids are used for Pen Kits, although 70% PG and 30% VG are the most popular Nicotine strengths vary.
Pod Kits are a modern and compact device for both MTL and Sub Ohm vaping. Juul Kit is one of the most famous representatives of such devices.
Sub Ohm kits The new generation is truly impressive. Designed for more experienced vapers wishing to produce vapour clouds, get more flavour, and longer battery life. Some models have more than one battery.
Mechanical Mods These devices are for advanced vapers allowing you to get the most out of your atomizer and coils inside. You will need knowledge and skills to use them. Please notice, that mechanical mod can be dangerous if misused and with the correct user can give a considerable performance.
Squonk mods are one of the new types of devices, they are intended only for a certain kind of atomizer.
Regardless of the type, vaping needs a vaping liquid referred to as e-liquids.
Vaping Liquid, Vaping Juice
A misconception about vaping liquids is that they're only water. But that's not true. Vaping liquid can contain water, but there are other materials, such as propylene glycol, vegetable glycerin, flavours, and nicotine.
Low-quality vaping ingredients are hazardous and cause serious complications. So please make sure that it's standard is high-quality and from a reputable company.
Unlike black-market dealers, reputable companies care about the health and safety of their customers. So, as long as you buy your vaping juice from a well-known brand, you should be fine.
Smoking Vs Vaping
As the name suggests, an e-cigarette inspired by traditional cigarettes, and both deliver nicotine. They can both be addictive, so children, teenagers, and pregnant women should avoid them.
The similarities are not many, but the differences are. According to the Royal College of Physicians, vaping nicotine is about 95% safer than smoking what's more, vaping leaves no bad smell, while many people hate the smell of cigarette smoke. However, handling and recharging an e-cigarette can be more complicated since there are no matches or lighters involved.
The dose of nicotine and vapour output are both adjustable in e-cigarettes—unlike traditional cigarettes. E-juices also comes in a wider variety of flavours, and they're more affordable than cigarettes.
Second-hand smoke is even more concerning than smoking cigarettes. But second-hand vapour is much less dangerous. Some studies also claim that it's non-toxic. Quitting vape is easier than smoking cigarettes because of the adjustable level of nicotine.
Overall, vapes are less risky than cigarettes. Of course, cigarettes have been around for centuries now, and there's a large body of research on cigarettes and their health risks. But still, the chemicals in cigarettes by far outnumber those in vapes.
Using Vapes to Quit Smoking
Many people turn to vapes to quit smoking. Should they?
When smoking cigarettes, you burn tobacco. You then inhale the smoke along with 7,000 other chemicals. The reason why cigarettes are so severely harmful to almost every organ is the other chemicals. Many of them are toxic.
Vaping nicotine can substitute smoking. An e-cigarette with a refillable tank is a more effective way to deliver than a disposable model. If you're a light smoker, an e-cigarette increases your chance of quitting.
Furthermore, some studies show e-cigarettes can be less addictive than traditional cigarettes.
One reason is that the dose of nicotine is adjustable, and you can slowly reduce it. However, some smokers start vaping and turn into dual users! Quitting needs a strong will and With the right attitude, vaping can set you on your path to quitting. Before making a final decision on how you'll stop, you should consult a health specialist. Merely switching to vaping nicotine won't guarantee that you'll quit smoking for good.
Is Vaping Bad for You?
Many sources are explaining the health risks associated with vaping. So far, scientists haven't studied the long-term effects of vaping. However, with the short-term effects and the material inside the e-juice, they can tell it is not harmless, but less harmful than cigarettes. We need more research on vaping and its potential harms.
Vaping Alerts
Like cigarettes, pregnant women should avoid vapes. The damage can cause future disabilities or disorders like the effect of alcohol, which you should avoid during pregnancy.
Children are another group that should avoid e-cigarettes—just like they shouldn't be allowed to smoke regular cigarettes.
Decades after smoking cigarettes had become popular; scientist realized their dangerous effects. Since the 1950s, many inventors have presented alternatives to traditional cigarettes. All of these alternatives aim to reduce the adverse side effects of smoking while maintaining the sense of pleasure you get from smoking.
In 2003, a Chinese pharmacist came up with the idea of vaping—using vapour to deliver nicotine and other chemicals to the body—as a safer and cleaner way to enjoy smokes. He planned to use an electronic device with a rechargeable battery to replace the cigarette. This device was created to look like a traditional cigarette in terms of both size and feel.
Is vaping safer than smoking? Definitely.
Overall, it's 95% less harmful than cigarettes, which is an impressive improvement.
Is it addictive? Yes. Everything with nicotine is addictive.
But they are easier to quit since the level of nicotine is adjustable. So, if you do decide to quit, you can easily lower the level.
Shall I start vaping? If you're under 18, definitely NO.
If you're a non-smoker, why do you want to do that? Many people are trying very hard to quit and get in your shoes if you're a smoker, of course! Use it to quit smoking.

redpajama_set_name: RedPajamaCommonCrawl


Wiebowo, Christiena (2001) A Study of the British influence to the igbo people and their reactions toward it in Chinua Achebe's Things Fall Apart. Bachelor thesis, Petra Christian University.
This Thesis is basically a study of the Igbo cultural changes which happened as a result of the British arrival in Chinua Achebe's Things Fall Apart. This novel tells the complexity of the Igbo's culture and because of the changes brought by the British finally the Igbo people reacted. Through this thesis, I try to find out how the culture of Igbo people which is very complex and beautiful finally has to "disappear". In this case, this thesis finds out the ways used by the British to influence the Igbo people to accept English practices and belief. This thesis examines how the reactions of the Igbo people toward the British influences and the outcomes of the Igbo people's different reactions. Therefore, in the analysis I mostly apply the literary theories of characterization and survival techniques as expressed in literature written by authors of African heritage. Besides, I also use the sociological theory along with the biography of Chinua Achebe and the history of the events in Things Fall Apart because what I analyse is about a culture of a society. Through the analysis, I find out that the ways used by the British are through the religious beliefs and practices, the social system and values, and also the government system. Then, I show the Igbo people's reactions as a result of the British influences; on one hand some of them accept the British practices and belief by using Christianity survival technique; while on the opposite hand, the rest of them reject the British practices and belief by using insurrection survival technique. Certainly, by having different survival techniques, finally they have different outcomes too; those who accept the British get a lot of advantages, while those who reject the British get nothing.


DOING: Mainly working, but have also made an effort to get outside and breath in fresh sea air when I can. I have also been trying to exercise often and started going to a yoga dance class as well as cycling a bit more.
HEARING: music – have been making more of an effort to listen to music and have it playing in the background. So lovely.
DRINKING: tea on shoots, chai tea (caffeine free) at home, peppermint tea & not enough water. Mid winter calls for all the warm drinks right?
EATING + COOKING: made a big batch of Dahl and it was so comforting and warming; sweet potato, chickpeas and coconut milk. Also feeling grateful for past Ellie who filled the freezer with soup, veggie spag Bol & date energy bites – so good on a busy work week. Also eating all the red pesto pasta with veggies and lashings of cheese – still my favourite most comforting meal (ever since I was little). Also we seem to have got into a weekend pastry habit – croissants and danish pastries seem to find their way to our house on a saturday (I'm not sad about it!). I have been trying to make sunday evening my meal prep evening for the week ahead, on the menu this week: courgette, sweet potato & broccoli soup, tomato aubergine lentil pasta sauce, tuscan bean chilli & cooking quinoa to have for lunches.
WANTING: it to properly snow in Plymouth this year. The rest of the country was blanketed late last week, but we barely got a dusting! I did however get to head up to the moors and see them in all their snowy glory for a shoot which was so beautiful and atmospheric.
LOOKING: forward to spring and not being so cold all the time, but I do also love the cosiness of this season.
DECIDING: What to make next in ceramics class, I'm loving lessons this term and actually seeing some improvement which is great! Really enjoying it.
GOING: to my first dance class. My amazing yoga teacher has just opened her own studio and she has also started dance classes there. I went to a taster class at the weekend and it was so fun. I'm definitely not the most natural dancer but it was so fun to move in such a lovely welcoming environment.
BUYING: I'm not really buying much of anything. But I did buy a cosy (and sustainably made) fat face jumper in the sale which I'm excited to wear. I also got an ebay bargain in the form of a light pink corduroy dungaree dress, I wore it this weekend and it makes me so happy.
MAKING: pots! I started my second pottery class two weeks ago and it has been great to get stuck in again. I find it so relaxing and it's great to be in a group of beginners and all learning together.
LEARNING: italian – or relearning as such. I've downloaded duolingo and am really loving it as a way to check in with my vocab and do a little every day. We are hoping to head there later this year so am trying to get back my conversational abilities for then!
PLANNING: ahead! For once, I am actually getting organised this year. I got a lovely planner which is really helping and I'm actually trying to know in advance when I'm doing what. Still lots of room for spontaneity but nice to have some things in the calendar. S works away a lot so it is sometimes hard to do but at least a few plans in place is lovely to have.
SAVOURING: Family time – I feel like I also put this for this category, but it's always true, family time and being with my grandparents is one of my greatest joys.
FEELING: Reflective, this time of year always has me taking stock of what I want from the year.


Let your dinner guests settle in with our cozy dining room chairs. From wicker to leather to slipcovered chairs Our Boat House has everything you could need. Create an atmosphere that invites your guests to linger a bit longer. Our slipcovered dining chairs are high quality with a long waterfall skirt that drops gracefully from the seat edge. Many of our dining room chairs also make greats desk chairs and can be carried into a living room as extra comfortable seating for company. For those who are looking for more of a unique look the wicker has a great texture, natural and beachy look to really add a touch of the sea.
23" X 24" X 35"