Package dk.brics.xact.operations

Source Code of dk.brics.xact.operations.XMLSource$WrappedSAXException

package dk.brics.xact.operations;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

import javax.xml.transform.sax.SAXSource;

import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLFilter;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.AttributesImpl;

import dk.brics.xact.Attribute;
import dk.brics.xact.AttributeGap;
import dk.brics.xact.Comment;
import dk.brics.xact.Element;
import dk.brics.xact.Node;
import dk.brics.xact.NodeVisitor;
import dk.brics.xact.ProcessingInstruction;
import dk.brics.xact.TemplateGap;
import dk.brics.xact.Text;
import dk.brics.xact.XML;

/**
* JAXP {@link SAXSource} for XML templates.
* Gaps in the XML templates are ignored.
*/ // TODO: optionally output gaps in desugared syntax
public class XMLSource extends SAXSource {

  private static final String LEXICAL_HANDLER_NAME = "http://xml.org/sax/properties/lexical-handler";

  private static final String FEATURE_NAMESPACES  = "http://xml.org/sax/features/namespaces";

  private XMLReader xmlreader = new SAXWriter();

  /**
   * Creates a JAXP {@link SAXSource} for the given XML template.
   */
  public XMLSource(XML x) {
    setDocument(x);
  }

  /**
   * Sets the XML template.
   */
  public void setDocument(XML x) {
    super.setInputSource(new XMLInputSource(x));
    setXMLReader(new SAXWriter());
  }

  /**
   * Returns the <code>XMLReader</code> to be used for the JAXP <code>SAXSource</code>.
   */
  @Override
  public XMLReader getXMLReader() {
    return xmlreader;
  }

  /**
   * Sets the XMLReader used for the JAXP {@link SAXSource}.
   */
  @Override
  public void setXMLReader(XMLReader reader)
  throws UnsupportedOperationException {
    if (reader instanceof SAXWriter) {
      this.xmlreader = reader;
    } else if (reader instanceof XMLFilter) {
      XMLFilter filter = (XMLFilter) reader;
      while (true) {
        XMLReader parent = filter.getParent();
        if (parent instanceof XMLFilter) {
          filter = (XMLFilter) parent;
        } else {
          break;
        }
      }
      filter.setParent(xmlreader);
      xmlreader = filter;
    } else {
      throw new UnsupportedOperationException();
    }
  }

  @Override
  public void setInputSource(InputSource inputSource) throws UnsupportedOperationException {
    throw new UnsupportedOperationException();
  }

  private class SAXWriter implements XMLReader {

    private ContentHandler contentHandler;

    private ErrorHandler errorHandler;

    private DTDHandler dtdHandler;

    private EntityResolver entityResolver;

    private LexicalHandler lexicalHandler;

    private AttributesImpl attributes = new AttributesImpl();

    private Map<String, Boolean> features = new HashMap<String, Boolean>();

    private Map<String, Object> properties = new HashMap<String, Object>();

    public void setContentHandler(ContentHandler c) {
      this.contentHandler = c;
    }

    public ContentHandler getContentHandler() {
      return contentHandler;
    }

    public void setErrorHandler(ErrorHandler e) {
      this.errorHandler = e;
    }

    public ErrorHandler getErrorHandler() {
      return errorHandler;
    }

    public DTDHandler getDTDHandler() {
      return dtdHandler;
    }

    public void setDTDHandler(DTDHandler d) {
      dtdHandler = d;
    }

    public EntityResolver getEntityResolver() {
      return entityResolver;
    }

    public void setEntityResolver(EntityResolver r) {
      entityResolver = r;
    }

    public LexicalHandler getLexicalHandler() {
      return lexicalHandler;
    }

    public void setLexicalHandler(LexicalHandler l) {
      lexicalHandler = l;
    }

    private void parse(XML x) throws SAXException {

      contentHandler.startDocument();
      final Stack<Entry> stack = new Stack<Entry>(); // using heap stack, avoids deep recursive calls
      stack.push(new Entry(Entry.Kind.START_NODE, x,null));
      final NamespacePrefixTracker ns = new NamespacePrefixTracker();

      while (!stack.isEmpty()) {
        final Entry en = stack.pop();
        switch (en.kind) {

        case START_NODE:
          try {
            en.node.visitBy(new NodeVisitor() {

              @Override
              public void visit(Text n) {
                String s = n.getString();
                try {
                  contentHandler.characters(s.toCharArray(), 0, s.length());
                } catch (SAXException e) {
                  throw new WrappedSAXException(e);
                }
                if (n.getNextSibling() != null)
                  stack.push(new Entry(Entry.Kind.START_NODE, n.getNextSibling(),null));
              }

              @Override
              public void visit(Comment n) {
                try {
                  lexicalHandler.comment(n.getValue().toCharArray(), 0, n.getValue().length());
                } catch (SAXException e) {
                  throw new WrappedSAXException(e);
                }
                if (n.getNextSibling() != null)
                  stack.push(new Entry(Entry.Kind.START_NODE, n.getNextSibling(),null));
              }

              @Override
              public void visit(ProcessingInstruction n) {
                try {
                  contentHandler.processingInstruction(n.getTarget(), n.getData());
                } catch (SAXException e) {
                  throw new WrappedSAXException(e);
                }
                if (n.getNextSibling() != null)
                  stack.push(new Entry(Entry.Kind.START_NODE, n.getNextSibling(),null));
              }

              @Override
              public void visit(Element n) {
                Map<String, String> nsdecls = ns.pushNamespaceDeclarations(n);
                for (Map.Entry<String, String> e : nsdecls.entrySet()) {
                  try {
                    contentHandler.startPrefixMapping(e.getKey(), e.getValue());
                  } catch (SAXException e1) {
                    throw new WrappedSAXException(e1);
                  }
                }

                attributes.clear();
                if (n.getFirstAttr() != null)
                  n.getFirstAttr().visitBy(this);
                try {
                  String qName = getQName(ns, n.getNamespace(),n.getLocalName());
                  contentHandler.startElement(getStringValue(n.getNamespace()), getStringValue(n.getLocalName()), getStringValue(qName), attributes);
                } catch (SAXException e) {
                  throw new WrappedSAXException(e);
                }
                stack.push(new Entry(Entry.Kind.END_ELEMENT, n,nsdecls));
                if (n.getFirstChild() != null)
                  stack.push(new Entry(Entry.Kind.START_NODE, n.getFirstChild(),null));
              }

              @Override
              public void visit(TemplateGap n) {
                // ignore
                if (n.getNextSibling() != null)
                  stack.push(new Entry(Entry.Kind.START_NODE, n.getNextSibling(),null));
              }

              @Override
              public void visit(Attribute n) {
                String qName = getQName(ns, n.getNamespace(),n.getLocalName());

                attributes.addAttribute(getStringValue(n.getNamespace()), getStringValue(n.getLocalName()), getStringValue(qName), "CDATA", getStringValue(n.getValue()));
                if (n.getNextAttr() != null)
                  n.getNextAttr().visitBy(this);
              }

              @Override
              public void visit(AttributeGap n) {
                // ignore
                if (n.getNextAttr() != null)
                  n.getNextAttr().visitBy(this);
              }

            });
          } catch (WrappedSAXException e) {
            throw e.e;
          }
          break;

        case END_ELEMENT:
          Element n = (Element) (en.node);
          String qName = getQName(ns, n.getNamespace(), n.getLocalName());
          contentHandler.endElement(n.getNamespace(), n.getLocalName(), qName);
          for (String p : en.nsdecls.keySet())
            contentHandler.endPrefixMapping(p);
          ns.popNamespaceDeclarations(en.nsdecls);
          if (n.getNextSibling() != null)
            stack.push(new Entry(Entry.Kind.START_NODE, n.getNextSibling(),null));
          break;
        }
      }
      contentHandler.endDocument();
    }

        /**
         * Returns s if s is not null and "" otherwise
         * @param s the string that may be null
         * @return a string that is not null
         */
        private String getStringValue(String s) {
            if (s == null)
                return "";
            return s;
        }

    private String getQName(NamespacePrefixTracker ns, String namespace, String localName) {
      if (namespace == null)
        namespace = "";
      String prefix = ns.getPrefix(namespace).peek();
      String qName;
      if (!prefix.equals("")) {
        qName = prefix + ":" + localName;
      } else {
        qName = localName;
      }
      return qName;
    }

    public void parse(InputSource s) throws IOException, SAXException {
      if (s instanceof XMLInputSource)
        parse(((XMLInputSource) s).getSource());
      else throw new IOException("Only XACT documents are supported");
    }

    public void parse(String s) throws IOException, SAXException {
      throw new IOException("Only XACT documents are supported");
    }

    public boolean getFeature(String name) throws SAXNotRecognizedException, SAXNotSupportedException {
      Boolean answer = features.get(name);
      return (answer != null) && answer.booleanValue();
    }

    public void setFeature(String name, boolean value) throws SAXNotRecognizedException, SAXNotSupportedException {
      if (name.equals(FEATURE_NAMESPACES))
        if (!value)
          throw new SAXNotSupportedException("Namespace feature is always supported in XACT");
      features.put(name, value);
    }

    public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException {
      if (name.equals(LEXICAL_HANDLER_NAME))
        return getLexicalHandler();
      return properties.get(name);
    }

    public void setProperty(String name, Object value) throws SAXNotRecognizedException, SAXNotSupportedException {
      if (name.equals(LEXICAL_HANDLER_NAME))
        setLexicalHandler((LexicalHandler) value);
      else
        properties.put(name, value);
    }
  }

  private static class XMLInputSource extends InputSource {

    private XML source;

    private XMLInputSource(XML source) {
      this.source = source;
    }

    public XML getSource() {
      return source;
    }
  }

  private static class Entry {

    enum Kind {
      START_NODE,
      END_ELEMENT
    }

    final Kind kind;

    final Node node;

    final Map<String, String> nsdecls;

    private Entry(Kind kind, Node node, Map<String, String> nsdecls) {
      this.kind = kind;
      this.node = node;
      this.nsdecls = nsdecls;
    }
  }

  private static class WrappedSAXException extends RuntimeException {

    private static final long serialVersionUID = 1L;
   
    private SAXException e;

    WrappedSAXException(SAXException e) {
      this.e = e;
    }
  }
}
TOP

Related Classes of dk.brics.xact.operations.XMLSource$WrappedSAXException

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.