Package org.jmol.adapter.readers.xml

Source Code of org.jmol.adapter.readers.xml.XmlReader$DummyResolver

/* $RCSfile$
* $Author: hansonr $
* $Date: 2006-08-02 11:48:43 -0500 (Wed, 02 Aug 2006) $
* $Revision: 5364 $
*
* Copyright (C) 2003-2005  Miguel, Jmol Development, www.jmol.org
*
* Contact: jmol-developers@lists.sf.net
*
*  This library is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public
*  License as published by the Free Software Foundation; either
*  version 2.1 of the License, or (at your option) any later version.
*
*  This library is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*  Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public
*  License along with this library; if not, write to the Free Software
*  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jmol.adapter.readers.xml;

import org.jmol.adapter.smarter.*;


import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;

import java.io.*;
import java.util.HashMap;

import netscape.javascript.JSObject;

import org.jmol.util.Logger;

/**
* A generic XML reader template -- by itself, does nothing.
*
* The actual readers are XmlCmlReader, XmlMolproReader (which is an
* extension of XmlCmlReader, XmlChem3dReader, and XmlOdysseyReader, which is wholely different.
*
*
* XmlReader takes all XML streams, whether from a file reader or from DOM.
* This class functions as a resolver, since it:
*  (1) identifying the specific strain of XML to be handled, and
*  (2) passing the responsibility on to the correct format-specific XML readers.
* There are parallel entry points and handler methods for reader and DOM. Each
* format-specific XML reader then assigns its own handler to manage the
* parsing of elements.
*
* In addition, this class handles generic XML tag parsing.
*
* XmlReader.JmolXmlHandler extends DefaultHandler is the generic interface to both reader and DOM element parsing.
*
* XmlCmlReader extends XmlReader and is where I'd like Andrew to take charge.
* XmlCmlReader.CmlHandler extends XmlReader.JmolXmlHandler is generic
*
* XmlMolproReader extends XmlCmlReader. If you feel like expanding on that, feel free.
* XmlMolproReader.MolprolHandler extends XmlCmlReader.CmlHandler adds Molpro-specific XML tag processing
*
* XmlChem3dReader extends XmlReader. That one is simple; no need to expand on it at this time.
* XmlChem3dReader.Chem3dHandler extends XmlReader.JmolXmlHandler is generic
*
* XmlOdysseyReader extends XmlReader. That one is simple; no need to expand on it at this time.
* XmlOdysseyReader.OdysseyHandler extends XmlReader.JmolXmlHandler is generic
*
* Note that the tag processing routines are shared between SAX
* and DOM processors. This means that attributes must be
* transformed from either Attributes (SAX) or JSObjects (DOM)
* to HashMap name:value pairs. This is taken care of in JmolXmlHandler
* for all readers.
*
* TODO 27/8/06:
*
* Several aspects of CifReader are NOT YET implemented here.
* These include loading a specific model when there are several,
* applying the symmetry, and loading fractional coordinates. [DONE for CML reader 2/2007 RMH]
*
* The DOM reader is NOT CHECKED OVER, and I do not think that it supports
* reading characters between start/end tags:
*
<tag>characters</tag>
*  If you work on this, please read formats other than CML into DOM so that
*  we can see that that works as well.
*  Test files:
*  molpro:  vib.xml
*  odyssey: water.xodydata
*  cml: a wide variety of files in data-files. Feel free to prune if some are
*  not of use.
*
* -Bob Hanson
*
*/

public class XmlReader extends AtomSetCollectionReader {

  //XmlReader subReader; // the actual reader; to be determined
  protected XmlReader parent;    // XmlReader itself; to be assigned by the subReader

  protected Atom atom;

  String[] implementedAttributes = { "id" };

  /////////////// file reader option //////////////

  public void initializeReader() throws Exception {
    XMLReader xmlReader = getXMLReader();
    if (xmlReader == null) {
      atomSetCollection = new AtomSetCollection("xml", this);
      atomSetCollection.errorMessage = "No XML reader found";
      return;
    }
    processXml(xmlReader);
    continuing = false;
  }

  private XMLReader getXMLReader() {
    XMLReader xmlr = null;
    // JAXP is preferred (comes with Sun JVM 1.4.0 and higher)
    if (xmlr == null
        && System.getProperty("java.version").compareTo("1.4") >= 0)
      xmlr = allocateXmlReader14();
    // Aelfred is the first alternative.
    if (xmlr == null)
      xmlr = allocateXmlReaderAelfred2();
    return xmlr;
  }

  private XMLReader allocateXmlReader14() {
    XMLReader xmlr = null;
    try {
      javax.xml.parsers.SAXParserFactory spf = javax.xml.parsers.SAXParserFactory
          .newInstance();
      spf.setNamespaceAware(true);
      javax.xml.parsers.SAXParser saxParser = spf.newSAXParser();
      xmlr = saxParser.getXMLReader();
      Logger.debug("Using JAXP/SAX XML parser.");
    } catch (Exception e) {
      Logger.debug("Could not instantiate JAXP/SAX XML reader: "
          + e.getMessage());
    }
    return xmlr;
  }

  private XMLReader allocateXmlReaderAelfred2() {
    XMLReader xmlr = null;
    try {
      xmlr = (XMLReader) this.getClass().getClassLoader().loadClass(
          "gnu.xml.aelfred2.XmlReader").newInstance();
      Logger.debug("Using Aelfred2 XML parser.");
    } catch (Exception e) {
      Logger.debug("Could not instantiate Aelfred2 XML reader!");
    }
    return xmlr;
  }

  private Object processXml(XMLReader xmlReader) throws Exception {
    atomSetCollection = new AtomSetCollection(readerName, this);
    Object res = getXmlReader();
    if (res instanceof String)
      return res;
    XmlReader thisReader = (XmlReader)res;
    thisReader.processXml(this, atomSetCollection, reader, xmlReader);
    return thisReader;
  }

  private Object getXmlReader() {   
    String className = null;
    Class atomSetCollectionReaderClass;
    String err = null;
    XmlReader thisReader = null;
    try {
      int pt = readerName.indexOf("(");
      String name = (pt < 0 ? readerName : readerName.substring(0, pt));
      className = Resolver.getReaderClassBase(name);
      atomSetCollectionReaderClass = Class.forName(className);//,true, Thread.currentThread().getContextClassLoader());
      thisReader = (XmlReader) atomSetCollectionReaderClass
          .newInstance();
    } catch (Exception e) {
      err = "File reader was not found:" + className;
      Logger.error(err);
      return err;
    }
    return thisReader;
  }
 
  protected void processXml(XmlReader parent,
                         AtomSetCollection atomSetCollection,
                         BufferedReader reader, XMLReader xmlReader) {
  }

  protected void parseReaderXML(XMLReader xmlReader) {
    xmlReader.setEntityResolver(new DummyResolver());
    InputSource is = new InputSource(reader);
    is.setSystemId("foo");
    try {
      xmlReader.parse(is);
    } catch (Exception e) {
      e.printStackTrace();
      atomSetCollection.errorMessage = "XML parsing error: " + e.getMessage();
    }
  }

  /////////////// DOM option //////////////

public void readAtomSetCollectionFromDOM(Object Node) {
    processXml((JSObject) Node);
  }

  private Object processXml(JSObject DOMNode) {
    atomSetCollection = new AtomSetCollection(readerName, this);
    String className = null;
    Class atomSetCollectionReaderClass;
    String err = null;
    XmlReader thisReader = null;
    String name = readerName.substring(0, readerName.indexOf("("));
    try {
      className = Resolver.getReaderClassBase(name);
      atomSetCollectionReaderClass = Class.forName(className);//,true, Thread.currentThread().getContextClassLoader());
      thisReader = (XmlReader) atomSetCollectionReaderClass
          .newInstance();
    } catch (Exception e) {
      err = "File reader was not found:" + className;
      Logger.error(err);
      return err;
    }
    thisReader.processXml(this, atomSetCollection, reader, DOMNode);
    return thisReader;
  }

  protected void processXml(XmlReader parent,
                            AtomSetCollection atomSetCollection,
                            BufferedReader reader, JSObject DOMNode) {
  }

  protected void processStartElement(String namespaceURI, String localName, String qName,
                           HashMap atts) {
    /*
     * specific to each xml reader
     */
  }

  /*
   *  keepChars is used to signal
   *  that characters between end tags should be kept
   * 
   */

  protected boolean keepChars;
  protected String chars;
  protected void setKeepChars(boolean TF) {
    keepChars = TF;
    chars = null;
  }

  protected void processEndElement(String uri, String localName, String qName) {
    /*
     * specific to each xml reader
     */
  }

  public static class DummyResolver implements EntityResolver {
    public InputSource resolveEntity(String publicID, String systemID)
        throws SAXException {
      if (Logger.debugging) {
        Logger.debug(
            "Jmol SAX EntityResolver not resolving:" +
            "\n  publicID: " + publicID +
            "\n  systemID: " + systemID
          );
      }
      return new InputSource(new BufferedReader(new StringReader("")));
    }
  }
 
  public class JmolXmlHandler extends DefaultHandler implements ErrorHandler {

    public JmolXmlHandler() {
    }

    public JmolXmlHandler(XMLReader xmlReader) {
      setHandler(xmlReader, this);
    }

    public void setHandler(XMLReader xmlReader, JmolXmlHandler handler) {
      try {
        xmlReader.setFeature("http://xml.org/sax/features/validation", false);
        xmlReader.setFeature("http://xml.org/sax/features/namespaces", true);
        xmlReader.setEntityResolver(handler);
        xmlReader.setContentHandler(handler);
        xmlReader.setErrorHandler(handler);
      } catch (Exception e) {
        Logger.error("ERROR IN XmlReader.JmolXmlHandler.setHandler", e);
      }

    }

    public void startDocument() {
    }

    public void endDocument() {
    }

    /*
     * see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
     * startElement and endElement should be extended in each reader
     */

    public HashMap atts;

    public void startElement(String namespaceURI, String localName,
                             String qName, Attributes attributes) {
      getAttributes(attributes);
      if (Logger.debugging) {
        Logger.debug("start " + localName);
      }
      startElement(namespaceURI, localName, qName);
    }

    private void startElement(String namespaceURI, String localName, String qName) {
      processStartElement(namespaceURI, localName, qName, atts);
    }

    public void endElement(String uri, String localName, String qName) {
      if (Logger.debugging) {
        Logger.debug("end " + localName);
      }
      processEndElement(uri, localName, qName);
    }

    // Won't work for DOM? -- equivalent of "innerHTML"

    public void characters(char[] ch, int start, int length) {
      if (keepChars) {
        if (chars == null) {
          chars = new String(ch, start, length);
        } else {
          chars += new String(ch, start, length);
        }
      }
    }

    // Methods for entity resolving, e.g. getting a DTD resolved

    public InputSource resolveEntity(String name, String publicId,
                                     String baseURI, String systemId) {
      if (Logger.debugging) {
        Logger.debug(
            "Not resolving this:" +
            "\n      name: " + name +
            "\n  systemID: " + systemId +
            "\n  publicID: " + publicId +
            "\n   baseURI: " + baseURI
          );
      }
      return null;
    }

    public InputSource resolveEntity(String publicId, String systemId) {
      if (Logger.debugging) {
        Logger.debug(
            "Not resolving this:" +
            "\n  publicID: " + publicId +
            "\n  systemID: " + systemId
          );
      }
      return null;
    }

    public void error(SAXParseException exception) {
      Logger.error("SAX ERROR:" + exception.getMessage());
    }

    public void fatalError(SAXParseException exception) {
      Logger.error("SAX FATAL:" + exception.getMessage());
    }

    public void warning(SAXParseException exception) {
      Logger.warn("SAX WARNING:" + exception.getMessage());
    }

    ////////////////////////////////////////////////////////////////

    // walk DOM tree given by JSObject. For every element, call
    // startElement with the appropriate strings etc., and then
    // endElement when the element is closed.

    protected void walkDOMTree(JSObject DOMNode) {
      String namespaceURI = (String) DOMNode.getMember("namespaceURI");
      String localName = (String) DOMNode.getMember("localName");
      String qName = (String) DOMNode.getMember("nodeName");
      JSObject attributes = (JSObject) DOMNode.getMember("attributes");
      getAttributes(attributes);
      startElement(namespaceURI, localName, qName);
      if (((Boolean) DOMNode.call("hasChildNodes", null))
          .booleanValue()) {
        for (JSObject nextNode = (JSObject) DOMNode.getMember("firstChild");
               nextNode != null;
               nextNode = (JSObject) nextNode.getMember("nextSibling"))
          walkDOMTree(nextNode);
      }
      endElement(namespaceURI, localName, qName);
    }

    ////////////////////

    private void getAttributes(Attributes attributes) {
      int nAtts = attributes.getLength();
      atts = new HashMap(nAtts);
      for (int i = nAtts; --i >= 0;)
        atts.put(attributes.getLocalName(i), attributes.getValue(i));
    }

    private void getAttributes(JSObject attributes) {
      if (attributes == null) {
        atts = new HashMap(0);
        return;
      }

      // load up only the implemented attributes

      int nAtts = ((Number) attributes.getMember("length")).intValue();
      atts = new HashMap(nAtts);
      for (int i = implementedAttributes.length; --i >= 0;) {
        Object[] attArgs = { implementedAttributes[i] };
        JSObject attNode = (JSObject) attributes.call("getNamedItem", attArgs);
        if (attNode != null) {
          String attLocalName = (String) attNode.getMember("name");
          String attValue = (String) attNode.getMember("value");
          atts.put(attLocalName, attValue);
        }
      }
    }
  }
}
TOP

Related Classes of org.jmol.adapter.readers.xml.XmlReader$DummyResolver

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.