package org.xmlpull.v1.dom2_builder;

import java.io.IOException;
import java.io.Reader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.DOMException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

public class DOM2XmlPullBuilder {
   protected Document newDoc() throws XmlPullParserException {
      try {
         DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
         DocumentBuilder builder = domFactory.newDocumentBuilder();
         DOMImplementation impl = builder.getDOMImplementation();
         return builder.newDocument();
      } catch (FactoryConfigurationError var4) {
         throw new XmlPullParserException("could not configure factory JAXP DocumentBuilderFactory: " + var4, (XmlPullParser)null, var4);
      } catch (ParserConfigurationException var5) {
         throw new XmlPullParserException("could not configure parser JAXP DocumentBuilderFactory: " + var5, (XmlPullParser)null, var5);
      }
   }

   protected XmlPullParser newParser() throws XmlPullParserException {
      XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
      return factory.newPullParser();
   }

   public Element parse(Reader reader) throws XmlPullParserException, IOException {
      Document docFactory = this.newDoc();
      return this.parse(reader, docFactory);
   }

   public Element parse(Reader reader, Document docFactory) throws XmlPullParserException, IOException {
      XmlPullParser pp = this.newParser();
      pp.setFeature("http://xmlpull.org/v1/doc/features.html#process-namespaces", true);
      pp.setInput(reader);
      pp.next();
      return this.parse(pp, docFactory);
   }

   public Element parse(XmlPullParser pp, Document docFactory) throws XmlPullParserException, IOException {
      Element root = this.parseSubTree(pp, docFactory);
      return root;
   }

   public Element parseSubTree(XmlPullParser pp) throws XmlPullParserException, IOException {
      Document doc = this.newDoc();
      Element root = this.parseSubTree(pp, doc);
      return root;
   }

   public Element parseSubTree(XmlPullParser pp, Document docFactory) throws XmlPullParserException, IOException {
      DOM2XmlPullBuilder.BuildProcess process = new DOM2XmlPullBuilder.BuildProcess();
      return process.parseSubTree(pp, docFactory);
   }

   private static void assertEquals(String expected, String s) {
      if (expected != null && !expected.equals(s) || expected == null && s == null) {
         throw new RuntimeException("expected '" + expected + "' but got '" + s + "'");
      }
   }

   private static void assertNotNull(Object o) {
      if (o == null) {
         throw new RuntimeException("expected no null value");
      }
   }

   public static void main(String[] args) throws Exception {
   }

   static class BuildProcess {
      private XmlPullParser pp;
      private Document docFactory;
      private boolean scanNamespaces;

      private BuildProcess() {
         this.scanNamespaces = true;
      }

      public Element parseSubTree(XmlPullParser pp, Document docFactory) throws XmlPullParserException, IOException {
         this.pp = pp;
         this.docFactory = docFactory;
         return this.parseSubTree();
      }

      private Element parseSubTree() throws XmlPullParserException, IOException {
         this.pp.require(2, (String)null, (String)null);
         String name = this.pp.getName();
         String ns = this.pp.getNamespace();
         String prefix = this.pp.getPrefix();
         String qname = prefix != null ? prefix + ":" + name : name;
         Element parent = this.docFactory.createElementNS(ns, qname);
         this.declareNamespaces(this.pp, parent);

         for(int i = 0; i < this.pp.getAttributeCount(); ++i) {
            String attrNs = this.pp.getAttributeNamespace(i);
            String attrName = this.pp.getAttributeName(i);
            String attrValue = this.pp.getAttributeValue(i);
            if (attrNs != null && attrNs.length() != 0) {
               String attrPrefix = this.pp.getAttributePrefix(i);
               String attrQname = attrPrefix != null ? attrPrefix + ":" + attrName : attrName;
               parent.setAttributeNS(attrNs, attrQname, attrValue);
            } else {
               parent.setAttribute(attrName, attrValue);
            }
         }

         while(this.pp.next() != 3) {
            if (this.pp.getEventType() == 2) {
               Element el = this.parseSubTree(this.pp, this.docFactory);
               parent.appendChild(el);
            } else {
               if (this.pp.getEventType() != 4) {
                  throw new XmlPullParserException("unexpected event " + XmlPullParser.TYPES[this.pp.getEventType()], this.pp, (Throwable)null);
               }

               String text = this.pp.getText();
               Text textEl = this.docFactory.createTextNode(text);
               parent.appendChild(textEl);
            }
         }

         this.pp.require(3, ns, name);
         return parent;
      }

      private void declareNamespaces(XmlPullParser pp, Element parent) throws DOMException, XmlPullParserException {
         int top;
         if (this.scanNamespaces) {
            this.scanNamespaces = false;
            top = pp.getNamespaceCount(pp.getDepth()) - 1;

            label42:
            for(int i = top; i >= pp.getNamespaceCount(0); --i) {
               String prefix = pp.getNamespacePrefix(i);

               for(int j = top; j > i; --j) {
                  String prefixJ = pp.getNamespacePrefix(j);
                  if (prefix != null && prefix.equals(prefixJ) || prefix != null && prefix == prefixJ) {
                     continue label42;
                  }
               }

               this.declareOneNamespace(pp, i, parent);
            }
         } else {
            for(top = pp.getNamespaceCount(pp.getDepth() - 1); top < pp.getNamespaceCount(pp.getDepth()); ++top) {
               this.declareOneNamespace(pp, top, parent);
            }
         }

      }

      private void declareOneNamespace(XmlPullParser pp, int i, Element parent) throws DOMException, XmlPullParserException {
         String xmlnsPrefix = pp.getNamespacePrefix(i);
         String xmlnsUri = pp.getNamespaceUri(i);
         String xmlnsDecl = xmlnsPrefix != null ? "xmlns:" + xmlnsPrefix : "xmlns";
         parent.setAttributeNS("http://www.w3.org/2000/xmlns/", xmlnsDecl, xmlnsUri);
      }

      // $FF: synthetic method
      BuildProcess(Object x0) {
         this();
      }
   }
}
