Package org.geotools.xml.test

Source Code of org.geotools.xml.test.XMLTestSupport

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
*
*    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;
*    version 2.1 of the License.
*
*    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.
*/
package org.geotools.xml.test;

import junit.framework.TestCase;
import org.eclipse.xsd.XSDSchema;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.defaults.DefaultPicoContainer;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.helpers.NamespaceSupport;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.geotools.xml.Binding;
import org.geotools.xml.Configuration;
import org.geotools.xml.DOMParser;
import org.geotools.xml.Encoder;
import org.geotools.xml.SchemaIndex;
import org.geotools.xml.XSD;
import org.geotools.xml.impl.BindingFactoryImpl;
import org.geotools.xml.impl.BindingLoader;
import org.geotools.xml.impl.BindingWalkerFactoryImpl;
import org.geotools.xml.impl.NamespaceSupportWrapper;
import org.geotools.xml.impl.SchemaIndexImpl;


/**
* Abstract test class to be used to unit test bindings.
* <p>
* Subclasses must implement the {@link #createConfiguration()} method. It must
* return a new instance of {@link Configuration}. Example:
*
* <pre>
*         <code>
*  public MailTypeBindingTest extends XMLTestSupport {
*
*      protected Configuration createConfiguration() {
*         return new MLConfiguration();
*      }
*  }
*         </code>
* </pre>
*
* </p>
* <p>
* The {@link #parse()} method is used to test binding parsing. Subclasses
* should call this from test methods after building up an instance document
* with {@link #document}. Example
*
* <pre>
*         <code>
*  public void testParsing() throws Exception {
*      //build up an instance document
*
*      //the root element
*      Element mailElement = document.createElementNS( ML.NAMESPACE, "mail" );
*      document.appendChild( mailElement );
*
*      mailElement.setAttribute( "id", "someId" );
*      ....
*
*      //call parse
*      Mail mail = (Mail) parse();
*
*      //make assertions
*      assertEquals( "someId", mail.getId() );
*  }
*         </code>
* </pre>
* </p>
*
* <p>
* The {@link #encode(Object, QName)} method is used to test binding encoding.
* Subclasses should call this method from test methods after creating an
* object to be encoded. Example:
*
* <pre>
*         <code>
* public void testEncoding() throws Exception {
*    //create the mail object
*    Mail mail = new Mail( "someId" );
*    mail.setEnvelope( ... );
*    ....
*
*    //call encode
*    Document document = encode( mail, new QName( ML.NAMESPACE, "mail" );
*
*    //make assertions
*    assertEquals( "mail", document.getDocumentElement().getNodeName() );
*    assertEquals( "someId", document.getDocumentElement().getAttribute( "id" ) );
* }
*         </code>
* </pre>
* </p>
*
* <p>
* The {@link #binding(QName)} method is used to obtain an instance of a
* particular binding. Subclasses should call this method to assert other
* properties of the binding, such as type mapping and execution mode. Example:
*
* <pre>
*         <code>
*  public void testType() {
*     //get an instance of the binding
*     Binding binding = binding( new QName( ML.NAMESPACE, "MailType" ) );
*
*     //make assertions
*     assertEquals( Mail.class, binding.getType() );
*  }
*
*  public void testExecutionMode() {
*    //get an instance of the binding
*    Binding binding = binding( new QName( ML.NAMESPACE, "MailType" ) );
*
*    //make assertions
*    assertEquals( Binding.OVERRIDE, binding.getExecutionMode() );
*  }
*         </code>
* </pre>
* </p>
*
* @author Justin Deoliveira, The Open Planning Project, jdeolive@openplans.org
*
*
*
*
* @source $URL$
*/
public abstract class XMLTestSupport extends TestCase {
    /**
     * Logging instance
     */
    protected static Logger logger = org.geotools.util.logging.Logging.getLogger(
            "org.geotools.xml.test");

    /**
     * the instance document
     */
    protected Document document;

    /**
     * additional namespace mappings
     */
    protected HashMap namespaceMappings;
    /**
     * Creates an empty xml document.
     */
    protected void setUp() throws Exception {
        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        docFactory.setNamespaceAware(true);

        document = docFactory.newDocumentBuilder().newDocument();
        namespaceMappings = new HashMap();
    }

    /**
     * Template method for subclasses to register namespace mappings on the
     * root element of an instance document.
     * <p>
     * Namespace mappings should be set as follows:
     * <pre>
     * <code>
     *        root.setAttribute( "xmlns:gml", http://www.opengis.net/gml" );
     * </code>
     * </pre>
     * </p>
     * <p>
     * Subclasses of this method should register the default namespace, the
     * default namesapce is the one returned by the configuration.
     * </p>
     * <p>
     * This method is intended to be extended or overiden. This implementation
     * registers the <code>xsi,http://www.w3.org/2001/XMLSchema-instance</code>
     * namespace.
     * </p>
     * @param root The root node of the instance document.
     * @deprecated use {@link #registerNamespaceMapping(String, String)}
     *
     */
    protected void registerNamespaces(Element root) {
        root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
    }

    /**
     * Registers a namespace mapping.
     * <p>
     * This mapping will be included in the "namespace context" of both the
     * parser and the encoder.
     * </p>
     * @param prefix The prefix of the namespace, not <code>null</code>.
     * @param uri The uri of the namespace, not <code>null</code>.
     */
    protected void registerNamespaceMapping( String prefix, String uri ) {
        namespaceMappings.put( prefix, uri );
    }
   
    /**
     * Tempalte method for subclasses to create the configuration to be used by
     * the parser.
     *
     * @return A parser configuration.
     */
    protected abstract Configuration createConfiguration();

    /**
     * Parses the build document, explicity specifying the type of the root
     * element.
     * <p>
     * This method should be called after building the entire document.
     *</p>
     * @param type The name of the type of the root element of the build document.
     */
    protected Object parse(QName type) throws Exception {
        Element root = document.getDocumentElement();

        if (root == null) {
            throw new IllegalStateException("Document has no root element");
        }

        Configuration config = createConfiguration();

        if (type != null) {
            config.getContext().registerComponentInstance("http://geotools.org/typeDefinition", type);
        }

        //register additional namespaces
        registerNamespaces(root);
        for ( Iterator e = namespaceMappings.entrySet().iterator(); e.hasNext(); ) {
            Map.Entry mapping = (Map.Entry) e.next();
            String prefix = (String) mapping.getKey();
            String uri = (String) mapping.getValue();
           
            root.setAttribute("xmlns:" + prefix, uri );
        }
       
        //process the schemaLocation, replace any schema locations that we know about
        if (root.hasAttribute("xsi:schemaLocation")) {
            XSD xsd = config.getXSD();
            List<XSD> deps = xsd.getAllDependencies();
            deps.add(xsd);
           
            String[] locations = root.getAttribute("xsi:schemaLocation").split(" +");
            for (int i = 0; i < locations.length; i += 2) {
                String uri = locations[i];
                for (XSD dep : deps) {
                    if (dep.getNamespaceURI().equals(uri)) {
                        locations[i+1] = dep.getSchemaLocation();
                    }
                }
            }
           
            StringBuffer joined = new StringBuffer();
            for (String s : locations) {
                joined.append(s).append(" ");
            }
            joined.setLength(joined.length()-1);
            root.setAttribute("xsi:schemaLocation", joined.toString());
        }
        else {
            //no schemaLocation attribute, add one for the schema for this config
            root.setAttribute("xsi:schemaLocation",
                config.getNamespaceURI() + " " + config.getSchemaFileURL());
        }
       

        DOMParser parser = new DOMParser(config, document);

        return parser.parse();
    }

    /**
     * Parses the built document.
     * <p>
     * This method should be called after building the entire document.
     *</p>
     */
    protected Object parse() throws Exception {
        return parse(null);
    }

    /**
     * Encodes an object, element name pair explicitly specifying the type of
     * the root element.
     *
     * @param object The object to encode.
     * @param element The name of the element to encode.
     * @param type The type of the element
     *
     * @return The object encoded.
     * @throws Exception
     */
    protected Document encode(Object object, QName element, QName type)
        throws Exception {
        Configuration configuration = createConfiguration();

        if (type != null) {
            //set the hint
            configuration.getContext()
                         .registerComponentInstance("http://geotools.org/typeDefinition", type);
        }

        XSDSchema schema = configuration.getXSD().getSchema();

        Encoder encoder = new Encoder(configuration, schema);
       
        //additional namespaces
        for ( Iterator e = namespaceMappings.entrySet().iterator(); e.hasNext(); ) {
            Map.Entry mapping = (Map.Entry) e.next();
            String prefix = (String) mapping.getKey();
            String uri = (String) mapping.getValue();
           
            encoder.getNamespaces().declarePrefix( prefix, uri );
        }
       
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        encoder.write(object, element, output);

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);

        return dbf.newDocumentBuilder().parse(new ByteArrayInputStream(output.toByteArray()));
    }

    /**
     * Encodes an object, element name pair.
     *
     * @param object The object to encode.
     * @param element The name of the element to encode.
     *
     * @return The object encoded.
     * @throws Exception
     */
    protected Document encode(Object object, QName element)
        throws Exception {
        return encode(object, element, null);
    }

    /**
     * Convenience method to dump the contents of the document to stdout.
     *
     *
     */
    protected void print(Node dom) throws Exception {
        TransformerFactory txFactory = TransformerFactory.newInstance();
        Transformer tx = txFactory.newTransformer();
        tx.setOutputProperty(OutputKeys.INDENT, "yes");
       
        tx.transform(new DOMSource(dom), new StreamResult(System.out));
    }

    /**
     * Convenience method for obtaining an instance of a binding.
     *
     * @param name The qualified name of the element,attribute,or type the
     * binding "binds" to, the key of the binding in the container.
     *
     * @return The binding.
     */
    protected Binding binding(QName name) {
        Configuration configuration = createConfiguration();

        //create the context
        MutablePicoContainer context = new DefaultPicoContainer();
        context = configuration.setupContext(context);

        //create the binding container
        Map bindings = configuration.setupBindings();
        BindingLoader bindingLoader = new BindingLoader(bindings);
//        MutablePicoContainer container = bindingLoader.getContainer();
//        container = configuration.setupBindings(container);
//        bindingLoader.setContainer(container);

        //register cmponents available to bindings at runtime
        context.registerComponentInstance(new BindingFactoryImpl(bindingLoader));

        //binding walker support
        context.registerComponentInstance(new BindingWalkerFactoryImpl(bindingLoader, context));

        //logger
        context.registerComponentInstance(logger);

        //setup the namespace support
        NamespaceSupport namespaces = new NamespaceSupport();
        HashMap mappings = new HashMap();

        try {
            for (Iterator d = configuration.getXSD().getDependencies().iterator(); d.hasNext();) {
                XSD xsd = (XSD) d.next();
                XSDSchema schema = xsd.getSchema();

                mappings.putAll(schema.getQNamePrefixToNamespaceMap());
            }

            mappings.putAll(configuration.getXSD().getSchema().getQNamePrefixToNamespaceMap());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        for (Iterator m = mappings.entrySet().iterator(); m.hasNext();) {
            Map.Entry mapping = (Map.Entry) m.next();
            String key = (String) mapping.getKey();

            if (key == null) {
                key = "";
            }

            namespaces.declarePrefix(key, (String) mapping.getValue());
        }

        context.registerComponentInstance(namespaces);
        context.registerComponentInstance(new NamespaceSupportWrapper(namespaces));
       
        SchemaIndex index = new SchemaIndexImpl( new XSDSchema[]{configuration.schema()} );
        context.registerComponentInstance(index);
       
        context.registerComponentInstance(configuration);
       
        return bindingLoader.loadBinding(name, context);
    }

    /**
     * Convenience method which parses the specified string into a dom and sets
     * the built document which is to be parsed.
     *
     * @param xml A string of xml
     */
    protected void buildDocument(String xml) throws Exception {
        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        docFactory.setNamespaceAware(true);

        document = docFactory.newDocumentBuilder().parse(new ByteArrayInputStream(xml.getBytes()));
    }

    /**
     * Convenience method for finding a node in a document which matches the
     * specified name.
     *
     */
    protected Element getElementByQName(Document dom, QName name) {
        return getElementByQName(dom.getDocumentElement(), name);
    }

    /**
     * Convenience method for finding a single descendant of a particular node
     * which matches the specified name.
     *
     */
    protected Element getElementByQName(Element parent, QName name) {
        NodeList nodes = parent.getElementsByTagNameNS(name.getNamespaceURI(), name.getLocalPart());

        if (nodes.getLength() == 0) {
            return null;
        }

        return (Element) nodes.item(0);
    }

    /**
     * Convenience method for finding nodes in a document which matche the
     * specified name.
     *
     */
    protected NodeList getElementsByQName(Document dom, QName name) {
        return getElementsByQName(dom.getDocumentElement(), name);
    }

    /**
     * Convenience method for finding decendants of a particular node which match
     * the specified name.
     *
     */
    protected NodeList getElementsByQName(Element parent, QName name) {
        return parent.getElementsByTagNameNS(name.getNamespaceURI(), name.getLocalPart());
    }
}
TOP

Related Classes of org.geotools.xml.test.XMLTestSupport

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.