alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.schema2beans;

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

import org.w3c.dom.*;
import org.xml.sax.*;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

/**
 *
 *
 */
public class GraphManager extends Object {
    
    public static interface Writer {
	public void write(OutputStream out, Document doc);
    }
    
    public static interface Factory {
        public org.w3c.dom.Document createDocument(InputStream in,
                                                   boolean validate);
    }
    
    Document	document = null;
    NodeFactory	factory = null;
    HashMap 	bindingsMap  = new HashMap();
    BaseBean	root;
    private boolean writeCData = false;
    
    //	When set to null (default), use XMLDocument instead
    private Factory		docFactory;
    private Writer		docWriter;

    private String		docTypePublic;
    private String		docTypeSystem;
    
    //
    //	The key is the input stream. This is how we can get the
    //	factory/writer when we are asked to build a Dom graph.
    //
    static Map	factoryMap = Collections.synchronizedMap(new HashMap(2));
    static Map	writerMap = Collections.synchronizedMap(new HashMap(2));
    

    public GraphManager(BaseBean root) {
        this.root = root;
    }
    
    /**
     *	Associate a factory to a stream
     */
    public static void setFactory(InputStream in,
				  GraphManager.Factory factory)  throws Schema2BeansException {
	setFactory(in, factory, null);
    }
    
    /**
     *  Set an external factory to use instead of the default one
     */
    public static void setFactory(InputStream in, GraphManager.Factory factory,
				  GraphManager.Writer writer) throws Schema2BeansException {
	if (in == null)
	    throw new Schema2BeansException(Common.getMessage(
		"InputStreamCantBeNull_msg"));
	
	if (factory != null)
	    GraphManager.factoryMap.put(in, factory);
	else
	    GraphManager.factoryMap.remove(in);
	
	if (writer != null)
	    GraphManager.writerMap.put(in, writer);
	else
	    GraphManager.writerMap.remove(in);
    }
    
    /**
     *  Set an external writer to use instead of the default one
     */
    public void setWriter(GraphManager.Writer writer) {
        this.docWriter = writer;
    }

    public void setWriteCData(boolean value) {
        writeCData = value;
    }
    
    public static Node createRootElementNode(String name) throws Schema2BeansRuntimeException {
        String s = "\n" +// NOI18N
            "<" + name + "/>";	// NOI18N

        ByteArrayInputStream in = new ByteArrayInputStream(s.getBytes());
        Document doc = GraphManager.createXmlDocument(in, false);
        NodeList children = doc.getChildNodes();
        int length = children.getLength();
        for (int i = 0; i < length; ++i) {
            Node node = children.item(i);
            if (node instanceof DocumentType) {
                //System.out.println("Found DocumentType where there should be none.");
                doc.removeChild(node);
                --length;
            }
        }
        return doc;
    }
    
    //
    //	Document created for this GraphManager. Called by the generated bean.
    //
    public void setXmlDocument(Node doc) throws Schema2BeansRuntimeException {
	if (doc instanceof Document) {
	    this.document = (Document)doc;
	    this.setNodeFactory((Document)doc);
	    
	    //
	    //	The factory/writer should know about the doc now
	    //	and no more about the original InputStream.
	    //	(if the user specified a factory/writer)
	    //
	    Object o = GraphManager.factoryMap.get(doc);
	    if (o != null) {
		this.docFactory = (GraphManager.Factory)o;
		GraphManager.factoryMap.remove(doc);
	    }
	    
	    o = GraphManager.writerMap.get(doc);
	    if (o != null) {
		this.docWriter = (GraphManager.Writer)o;
		GraphManager.writerMap.remove(doc);
	    }
	}
	else
	    throw new Schema2BeansRuntimeException(Common.getMessage(
		"CantFindFactory_msg"));
    }
    
    
    /**
     * This returns the DOM Document object, root
     * of the current DOM graph.  Operations that cause structural
     * modifications to the DOM graph are not allowed.  Indeed,
     * modifying the DOM graph directly would cause the bean graph
     * and its internal representation to be out of sync.
     */
    public Document getXmlDocument() {
	return this.document;
    }
    
    public void setDoctype(String publicId, String systemId) {
        //System.out.println("GraphManager.setDoctype: publicId="+publicId+" systemId="+systemId);
	this.docTypePublic = publicId;
	this.docTypeSystem = systemId;
    }
    
    /**
     *	Parse the DOM tree until the element named 'name' is found.
     *	Return the node of the name or null if not found.
     *	This method is used by the root bean generated class to get
     *	the root element of the DOM tree and start building the
     *	bean graph from here.
     */
    public static Node getElementNode(String name, Node doc) {
	Node n;
	for (n = doc.getFirstChild(); n != null; n = n.getNextSibling()) {
	    if (n.getNodeType() == Node.ELEMENT_NODE
	    && n.getNodeName().equals(name)) {
		break;
	    }
	}
	return n;
    }
    
    /**
     *	This method is called by the createRoot() method of the root bean
     *	(part of the BaseBean class). The doc might not be available
     *	at the time of this call. In such a case, the method
     *	completeRootBinding is called afterwards with the doc value to complete
     *	the setup of the root.
     *
     *	This makes sure that the root element of the object bindings
     *	between the beans and the DOM Nodes is created, before that the
     *	recursing creation of the graph begins.
     */
    public void createRootBinding(BaseBean beanRoot, BeanProp prop, Node doc) throws Schema2BeansException {
	prop.registerDomNode(doc, null, beanRoot);
	if (doc != null)
	    this.bindingsMap.put(doc, beanRoot.binding);
    }
    
    public void completeRootBinding(BaseBean beanRoot, Node doc) {
	this.bindingsMap.put(doc, beanRoot.binding);
	beanRoot.binding.setNode(doc);
    }
    
    /**
     *	This method sets the DOM nodes factory.
     */
    public void setNodeFactory(Document doc) {
	this.factory = new NodeFactory(doc);
    }
    
    /**
     *  Return the DOM node factory
     */
    public NodeFactory getNodeFactory() {
	return this.factory;
    }
    
    /**
     *	Return the root of the bean graph
     */
    public BaseBean getBeanRoot() {
	return this.root;
    }

    /**
     *	OutputStream version of write()
     */
    void write(OutputStream out) throws IOException, Schema2BeansException {
        //
        //	Code specific to the DOM implementation:
        //
        if (this.document == null)
            throw new Schema2BeansException(Common.getMessage("CantGetDocument_msg"));
        if (this.docWriter != null)
            this.docWriter.write(out, this.document);
        else {
            XMLUtil.DOMWriter domWriter = getDOMWriter();
            domWriter.write(out, document);
        }
    }

    protected void write(OutputStream out, String encoding) throws java.io.IOException {
        XMLUtil.DOMWriter domWriter = getDOMWriter();
        domWriter.write(out, encoding, document);
    }

    protected void write(java.io.Writer out) throws java.io.IOException {
        XMLUtil.DOMWriter domWriter = getDOMWriter();
        domWriter.setWriter(out);
        domWriter.write(document);
    }

    protected void write(java.io.Writer out, String encoding) throws java.io.IOException {
        XMLUtil.DOMWriter domWriter = getDOMWriter();
        domWriter.setWriter(out);
        domWriter.write(document, encoding);
    }

    public void write(java.io.Writer out, Node node) throws java.io.IOException, Schema2BeansException {
        XMLUtil.DOMWriter domWriter = getDOMWriter();
        domWriter.setWriter(out);
        domWriter.write(node);
    }

    protected XMLUtil.DOMWriter getDOMWriter() {
        XMLUtil.DOMWriter domWriter = new XMLUtil.DOMWriter();
        domWriter.setDocTypePublic(docTypePublic);
        domWriter.setDocTypeSystem(docTypeSystem);
        domWriter.setWriteCData(writeCData);
        return domWriter;
    }
    
    /**
     * Take the current DOM tree and readjust whitespace so that it
     * looks pretty.
     */
    public void reindent(String indent) {
        XMLUtil.reindent(document, indent);
    }

    /**
     * Indent by 2 spaces for every @level.
     */
    protected static void printLevel(java.io.Writer out, int level, String indent) throws java.io.IOException {
        StringBuffer outBuf = new StringBuffer();
        printLevel(outBuf, level, indent);
        out.write(outBuf.toString());
    }

    protected static void printLevel(StringBuffer out, int level, String indent) {
        for (int i = 0; i < level; ++i) {
            out.append(indent);
        }
    }
    
    protected static void printLevel(java.io.Writer out, int level, String indent, String text) throws java.io.IOException {
        StringBuffer outBuf = new StringBuffer();
        printLevel(outBuf, level, indent, text);
        out.write(outBuf.toString());
    }

    protected static void printLevel(OutputStream out, int level, String indent, String text) throws java.io.IOException {
        OutputStreamWriter w = new OutputStreamWriter(out);
        printLevel(w, level, indent, text);
        w.flush();
    }

    protected static void printLevel(StringBuffer out, int level,
                                     String indent, String text) {
        printLevel(out, level, indent);
        out.append(text);
    }

    /**
     *	Creates a DOM document from the input stream.
     */
    public static Document createXmlDocument(InputStream in, boolean validate) throws Schema2BeansRuntimeException {
	return createXmlDocument(in, validate, null);
    }

    private static InputStream tee(InputStream in) throws IOException {
        byte[] buf = new byte[4096];
        ByteArrayOutputStream ba = new ByteArrayOutputStream();
        int totalLength = 0;
        int len;
        while ((len = in.read(buf, 0, 4096)) > 0) {
            ba.write(buf, 0, len);
            totalLength += len;
        }
        System.out.println("schema2beans: in (length="+totalLength+"):");
        System.out.println(ba.toString());
        ByteArrayInputStream bain = new ByteArrayInputStream(ba.toByteArray());
        return bain;
    }

    /**
     *	Creates a DOM document from the input stream.
     */
    public static Document createXmlDocument(InputStream in, boolean validate,
                                             EntityResolver er) throws Schema2BeansRuntimeException {
        if (in == null)
            throw new IllegalArgumentException("in == null");	// NOI18N
        try {
            if (DDLogFlags.debug) {
                // Dump the contents to stdout
                in = tee(in);
            }
	    
            //
            //	Change the references to map the newly created doc
            //	The BaseBean instance is not created yet. The doc
            //	document will be used to get back the factories.
            //
            Object o = GraphManager.factoryMap.get(in);
            if (o != null) {
                GraphManager.Factory f = (GraphManager.Factory)o;
		
                Document doc = f.createDocument(in, validate);
		
                GraphManager.factoryMap.remove(in);
                GraphManager.factoryMap.put(doc, o);
		
                Object o2 = GraphManager.writerMap.get(in);
                if (o2 != null) {
                    GraphManager.writerMap.remove(in);
                    GraphManager.writerMap.put(doc, o2);
                }
                return doc;
            }
            else {
                return createXmlDocument(new InputSource(in), validate, er, null);
            }
        } catch (Schema2BeansException e) {
            throw new Schema2BeansRuntimeException(e);
        } catch (IOException e) {
            throw new Schema2BeansRuntimeException(e);
        }
    }


    public static Document createXmlDocument(InputSource in, boolean validate) throws Schema2BeansException {
	return createXmlDocument(in, validate, null, null);
    }


    public static Document createXmlDocument(InputSource in, boolean validate,
                                             EntityResolver er, ErrorHandler eh) throws Schema2BeansException {
        if (in == null)
            throw new IllegalArgumentException("in == null");	// NOI18N
        if (validate == false && er == null) {
            // The client is not interested in any validation, so make
            // see to it that any entity resolution doesn't hit the network
            er = NullEntityResolver.newInstance();
        }
        try {
            //	Build a Document using JAXP
            DocumentBuilderFactory dbf =
                DocumentBuilderFactory.newInstance();
            dbf.setValidating(validate);

            DocumentBuilder db = dbf.newDocumentBuilder();
            if (er != null)
                db.setEntityResolver(er);
            if (eh != null)
                db.setErrorHandler(eh);

            if (DDLogFlags.debug) {
                System.out.println("createXmlDocument: validate="+validate+" dbf="+dbf+" db="+db+" er="+er);
            }

            return db.parse(in);
        } catch (javax.xml.parsers.ParserConfigurationException e) {
            throw new Schema2BeansNestedException(Common.getMessage("CantCreateXMLDOMDocument_msg"), e);
        } catch (org.xml.sax.SAXException e) {
            throw new Schema2BeansNestedException(Common.getMessage("CantCreateXMLDOMDocument_msg"), e);
        } catch (IOException e) {
            throw new Schema2BeansNestedException(Common.getMessage("CantCreateXMLDOMDocument_msg"), e);
        }
    }
    
    /**
     *	This method is called by the generated beans when they are
     *	building themselves from a DOM tree.
     *	Typically, the first root bean calls this method with the
     *	DOM root node and the list of the properties that are expected
     *	under this node.
     *	This method parses the DOM sub-node of the node and matches their names
     *	with the names of the properties. When a match is found, the
     *	bean property object is called with the node found. If the node
     *	has no match in the bean properties, the node is ignored but
     *	the event is logged as it might reveal a problem in the bean tree
     *	(DTD element missing in the bean class graph).
     *
     */
    public void fillProperties(BeanProp[] prop, Node node) throws Schema2BeansException {
        BaseBean 	bean;
        DOMBinding 	binding, newBinding;
	
        if (prop == null || node == null)
            return;
	
        if (this.bindingsMap.get(node) == null) {
            throw new Schema2BeansException(Common.getMessage(
                                                              "CurrentNodeHasNoBinding_msg", new Integer(node.hashCode())));
        }

        // Store the property's dtdName's into a map for fast lookup,
        // and be able to handle multiple properties with the same name.
        Map dtdName2Prop = new HashMap();	// Map
        Map dupDtdNames = new HashMap();	// Map>
        for(int i=0; i Comment
     *	indexed property:	/Book/Chapter.4  	-> Chapter
     *	attribute:		/Book/Chapter.2:title	-> Chapter
     *
     */
    public static String getPropertyName(String name) {
	int i = name.lastIndexOf('/');
	if (i != -1)
	    name = name.substring(i+1);
	//	Remove the index value
	i = name.lastIndexOf('.');
	if (i != -1)
	    name = name.substring(0, i);
	//	If there is a still an attribute, remove it
	i = name.lastIndexOf(':');
	if (i != -1)
	    name = name.substring(0, i);
	
	return name;
    }
    
    /**
     *	Return the name of the attribute if this is the name of an attribute,
     *	return null otherwise.
     *
     *	single property: 	/Book/Chapter.2/Comment	-> null
     *	indexed property:	/Book/Chapter.4  	-> null
     *	attribute:		/Book/Chapter.2:title	-> title
     *
     */
    public String getAttributeName(String name) {
	int i = name.lastIndexOf(':');
	if (i != -1)
	    name = name.substring(i+1);
	else
	    name = null;
	return name;
    }
    
    /**
     *	Return true if this is the name of an attribute
     */
    public boolean isAttribute(String name) {
	int i = name.lastIndexOf(':');
	return (i != -1);
    }
    
    /**
     *	Return the index value of the property, as a string
     */
    private static String extractPropertyIndex(String name) {
	int i = name.lastIndexOf('/');
	if (i != -1)
	    name = name.substring(i+1);
	i = name.lastIndexOf('.');
	if (i != -1) {
	    name = name.substring(i+1);
	    i = name.lastIndexOf(':');
	    if (i != -1)
		name = name.substring(0, i);
	}
	else
	    name = null;
	return name;
    }
    
    
    /**
     *	If the property is an indexed property, return the index of
     *	the property.
     */
    public int getPropertyIndex(String name) {
        return getPropertyIndex(root, name);
    }
    public static int getPropertyIndex(Bean theRoot, String name) {
        String index = extractPropertyIndex(name);
        if (index != null) {
            int i = index.lastIndexOf('i');
            if (i != -1) {
                //  This is a removed property - return the old value
                return Integer.parseInt(index.substring(i+1));
            }
            else {
                //  Get the current index value
                Bean bean = getPropertyParent(theRoot, name);
                if (bean != null) {
                    BeanProp bp = bean.beanProp(getPropertyName(name));
		    
                    if (bp != null)
                        return bp.idToIndex(Integer.parseInt(index, 16));
                }
            }
        }
	
        return -1;
    }
    
    //
    //	Events misc. methods
    //
    /////////////////////////////
    
    static public void debug(boolean d) {
	DDLogFlags.debug = d;
    }
    
    //
    //	Default values for scalar types. The idea is to allow the user to
    //	change the following default values (TODO).
    //
    public Object defaultScalarValue(int type) {
	switch(type & Common.MASK_TYPE) {
	    case Common.TYPE_STRING:
		return "";	// NOI18N
	    case Common.TYPE_BOOLEAN:
		return Boolean.FALSE;
	    case Common.TYPE_BYTE:
		return new Byte((byte)0);
	    case Common.TYPE_CHAR:
		return new Character('\0');
	    case Common.TYPE_SHORT:
		return new Short((short)0);
	    case Common.TYPE_INT:
		return new Integer(0);
	    case Common.TYPE_LONG:
		return new Long(0);
	    case Common.TYPE_FLOAT:
		return new Float(0.0);
	    case Common.TYPE_DOUBLE:
		return new Double(0.0);
	    default:
            throw new IllegalArgumentException(Common.getMessage("UnknownType", type));
	}
    }
}

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.