blob: 36c87a6bd6bbed02f837a38f408074fcd1eeb5b3 [file] [log] [blame]
/* $Id$
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.digester3;
import static org.apache.commons.digester3.binder.DigesterLoader.newLoader;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.digester3.binder.AbstractRulesModule;
import org.apache.commons.digester3.binder.NodeCreateRuleProvider.NodeType;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
/**
* <p>
* Test case for the <code>NodeCreateRule</code>.
*
* @author Christopher Lenz
*/
public class NodeCreateRuleTestCase
{
// ----------------------------------------------------- Instance Variables
/**
* Simple test xml document used in the tests.
*/
protected final static String TEST_XML = "<?xml version='1.0'?><root>ROOT BODY<alpha>ALPHA BODY</alpha>"
+ "<beta>BETA BODY</beta><gamma>GAMMA BODY</gamma></root>";
// ------------------------------------------------ Individual Test Methods
/**
* Tests simple element construction, using the {@link #TEST_XML} XML input data.
*/
@Test
public void testInvalidNodeTypes()
throws Exception
{
try
{
Rule rule = new NodeCreateRule( Node.ATTRIBUTE_NODE );
fail( "IllegalArgumentException expected for type ATTRIBUTE_NODE" );
assertNotNull( rule ); // just to prevent compiler warning on unused var
}
catch ( IllegalArgumentException iae )
{
// expected
}
try
{
Rule rule = new NodeCreateRule( Node.CDATA_SECTION_NODE );
fail( "IllegalArgumentException expected for type " + "CDATA_SECTION_NODE" );
assertNotNull( rule ); // just to prevent compiler warning on unused var
}
catch ( IllegalArgumentException iae )
{
// expected
}
try
{
Rule rule = new NodeCreateRule( Node.COMMENT_NODE );
fail( "IllegalArgumentException expected for type COMMENT_NODE" );
assertNotNull( rule ); // just to prevent compiler warning on unused var
}
catch ( IllegalArgumentException iae )
{
// expected
}
try
{
Rule rule = new NodeCreateRule( Node.DOCUMENT_NODE );
fail( "IllegalArgumentException expected for type DOCUMENT_NODE" );
assertNotNull( rule ); // just to prevent compiler warning on unused var
}
catch ( IllegalArgumentException iae )
{
// expected
}
try
{
Rule rule = new NodeCreateRule( Node.DOCUMENT_TYPE_NODE );
fail( "IllegalArgumentException expected for type " + "DOCUMENT_TYPE_NODE" );
assertNotNull( rule ); // just to prevent compiler warning on unused var
}
catch ( IllegalArgumentException iae )
{
// expected
}
try
{
Rule rule = new NodeCreateRule( Node.ENTITY_NODE );
fail( "IllegalArgumentException expected for type ENTITY_NODE" );
assertNotNull( rule ); // just to prevent compiler warning on unused var
}
catch ( IllegalArgumentException iae )
{
// expected
}
try
{
Rule rule = new NodeCreateRule( Node.ENTITY_REFERENCE_NODE );
fail( "IllegalArgumentException expected for type " + "ENTITY_REFERENCE_NODE" );
assertNotNull( rule ); // just to prevent compiler warning on unused var
}
catch ( IllegalArgumentException iae )
{
// expected
}
try
{
Rule rule = new NodeCreateRule( Node.NOTATION_NODE );
fail( "IllegalArgumentException expected for type NOTATION_NODE" );
assertNotNull( rule ); // just to prevent compiler warning on unused var
}
catch ( IllegalArgumentException iae )
{
// expected
}
try
{
Rule rule = new NodeCreateRule( Node.PROCESSING_INSTRUCTION_NODE );
fail( "IllegalArgumentException expected for type " + "PROCESSING_INSTRUCTION_NODE" );
assertNotNull( rule ); // just to prevent compiler warning on unused var
}
catch ( IllegalArgumentException iae )
{
// expected
}
try
{
Rule rule = new NodeCreateRule( Node.TEXT_NODE );
fail( "IllegalArgumentException expected for type TEXT_NODE" );
assertNotNull( rule ); // just to prevent compiler warning on unused var
}
catch ( IllegalArgumentException iae )
{
// expected
}
}
/**
* Tests simple element construction, using the {@link #TEST_XML} XML input data.
*/
@Test
public void testElement()
throws SAXException, IOException
{
Digester digester = newLoader( new AbstractRulesModule()
{
@Override
protected void configure()
{
forPattern( "root/alpha" ).createNode();
}
}).newDigester();
Element element = digester.parse( new StringReader( TEST_XML ) );
assertNotNull( element );
assertEquals( "alpha", element.getNodeName() );
assertNull( element.getLocalName() );
assertNull( element.getNamespaceURI() );
assertEquals( 1, element.getChildNodes().getLength() );
assertEquals( "ALPHA BODY", element.getFirstChild().getNodeValue() );
}
/**
* Tests simple fragment construction, using the {@link #TEST_XML} XML input data.
*/
@Test
public void testDocumentFragment()
throws SAXException, IOException
{
Digester digester = newLoader( new AbstractRulesModule()
{
@Override
protected void configure()
{
forPattern( "root" ).createNode().ofType( NodeType.DOCUMENT_FRAGMENT );
}
}).newDigester();
DocumentFragment fragment = digester.parse( new StringReader( TEST_XML ) );
assertNotNull( fragment );
assertEquals( 4, fragment.getChildNodes().getLength() );
Node rootBody = fragment.getFirstChild();
assertEquals( Node.TEXT_NODE, rootBody.getNodeType() );
assertEquals( "ROOT BODY", rootBody.getNodeValue() );
Node alpha = fragment.getChildNodes().item( 1 );
assertEquals( Node.ELEMENT_NODE, alpha.getNodeType() );
assertEquals( "alpha", alpha.getNodeName() );
assertNull( ( (Element) alpha ).getLocalName() );
assertNull( ( (Element) alpha ).getNamespaceURI() );
assertEquals( 1, alpha.getChildNodes().getLength() );
assertEquals( "ALPHA BODY", alpha.getFirstChild().getNodeValue() );
Node beta = fragment.getChildNodes().item( 2 );
assertEquals( Node.ELEMENT_NODE, beta.getNodeType() );
assertEquals( "beta", beta.getNodeName() );
assertNull( ( (Element) beta ).getLocalName() );
assertNull( ( (Element) beta ).getNamespaceURI() );
assertEquals( 1, beta.getChildNodes().getLength() );
assertEquals( "BETA BODY", beta.getFirstChild().getNodeValue() );
Node gamma = fragment.getChildNodes().item( 3 );
assertEquals( Node.ELEMENT_NODE, gamma.getNodeType() );
assertEquals( "gamma", gamma.getNodeName() );
assertNull( ( (Element) gamma ).getLocalName() );
assertNull( ( (Element) gamma ).getNamespaceURI() );
assertEquals( 1, gamma.getChildNodes().getLength() );
assertEquals( "GAMMA BODY", gamma.getFirstChild().getNodeValue() );
}
/**
* Tests whether control is returned to digester after fragment construction.
*/
@Test
public void testNested()
throws SAXException, IOException
{
Digester digester = newLoader( new AbstractRulesModule()
{
@Override
protected void configure()
{
forPattern( "root" ).createObject().ofType( ArrayList.class );
forPattern( "root/a/b" ).createNode().ofType( NodeType.DOCUMENT_FRAGMENT )
.then()
.setRoot( "add" );
forPattern( "root/b" ).createObject().ofType( String.class )
.then()
.setRoot( "add" );
}
}).newDigester();
List<?> list = digester.parse( getInputStream( "Test4.xml" ) );
assertNotNull( list );
assertEquals( 2, list.size() );
assertTrue( list.get( 0 ) instanceof DocumentFragment );
DocumentFragment fragment = (DocumentFragment) list.get( 0 );
assertEquals( Node.ELEMENT_NODE, fragment.getFirstChild().getNodeType() );
Element a = (Element) fragment.getFirstChild();
assertEquals( "a", a.getNodeName() );
assertEquals( 1, a.getAttributes().getLength() );
assertEquals( "THREE", a.getAttribute( "name" ) );
assertTrue( list.get( 1 ) instanceof String );
}
/**
* Tests whether attributes are correctly imported into the fragment, using the example in the Test1 XML file.
*/
@Test
public void testAttributes()
throws SAXException, IOException
{
Digester digester = newLoader( new AbstractRulesModule()
{
@Override
protected void configure()
{
forPattern( "employee" ).createNode().ofType( NodeType.DOCUMENT_FRAGMENT );
}
}).newDigester();
DocumentFragment fragment = digester.parse( getInputStream( "Test1.xml" ) );
assertNotNull( fragment );
assertEquals( 2, fragment.getChildNodes().getLength() );
assertEquals( Node.ELEMENT_NODE, fragment.getFirstChild().getNodeType() );
Element address1 = (Element) fragment.getFirstChild();
assertEquals( "address", address1.getNodeName() );
assertEquals( 5, address1.getAttributes().getLength() );
assertEquals( "home", address1.getAttribute( "type" ) );
assertEquals( "Home Street", address1.getAttribute( "street" ) );
assertEquals( "Home City", address1.getAttribute( "city" ) );
assertEquals( "HS", address1.getAttribute( "state" ) );
assertEquals( "HmZip", address1.getAttribute( "zipCode" ) );
assertEquals( Node.ELEMENT_NODE, fragment.getLastChild().getNodeType() );
Element address2 = (Element) fragment.getLastChild();
assertEquals( "address", address2.getNodeName() );
assertEquals( 5, address2.getAttributes().getLength() );
assertEquals( "office", address2.getAttribute( "type" ) );
assertEquals( "Office Street", address2.getAttribute( "street" ) );
assertEquals( "Office City", address2.getAttribute( "city" ) );
assertEquals( "OS", address2.getAttribute( "state" ) );
assertEquals( "OfZip", address2.getAttribute( "zipCode" ) );
}
/**
* Tests whether namespaces are handled correctly, using the example from the file Test3 XML file.
*/
@Test
public void testNamespaces()
throws SAXException, IOException
{
Digester digester = newLoader( new AbstractRulesModule()
{
@Override
protected void configure()
{
forPattern( "employee" ).createNode().ofType( NodeType.DOCUMENT_FRAGMENT );
}
})
.setNamespaceAware( true )
.newDigester();
DocumentFragment fragment = digester.parse( getInputStream( "Test3.xml" ) );
assertNotNull( fragment );
assertEquals( 2, fragment.getChildNodes().getLength() );
assertEquals( Node.ELEMENT_NODE, fragment.getFirstChild().getNodeType() );
Element address1 = (Element) fragment.getFirstChild();
assertEquals( "address", address1.getNodeName() );
assertEquals( "http://commons.apache.org/digester/Bar", address1.getNamespaceURI() );
assertEquals( "address", address1.getLocalName() );
assertEquals( 5, address1.getAttributes().getLength() );
assertEquals( "home", address1.getAttribute( "type" ) );
assertEquals( "Home Street", address1.getAttribute( "street" ) );
assertEquals( "Home City", address1.getAttribute( "city" ) );
assertEquals( "HS", address1.getAttribute( "state" ) );
assertEquals( "HmZip", address1.getAttribute( "zipCode" ) );
assertEquals( Node.ELEMENT_NODE, fragment.getLastChild().getNodeType() );
Element address2 = (Element) fragment.getLastChild();
assertEquals( "address", address2.getNodeName() );
assertEquals( "http://commons.apache.org/digester/Bar", address2.getNamespaceURI() );
assertEquals( "address", address2.getLocalName() );
assertEquals( 5, address2.getAttributes().getLength() );
assertEquals( "office", address2.getAttribute( "type" ) );
assertEquals( "Office Street", address2.getAttribute( "street" ) );
assertEquals( "Office City", address2.getAttribute( "city" ) );
assertEquals( "OS", address2.getAttribute( "state" ) );
assertEquals( "OfZip", address2.getAttribute( "zipCode" ) );
}
/**
* Tests whether namespaced attributes are handled correctly, using the example from the file Test10 XML file.
*/
@Test
public void testNamespacedAttribute()
throws SAXException, IOException
{
Digester digester = newLoader( new AbstractRulesModule()
{
@Override
protected void configure()
{
forPattern( "employee" ).createNode().ofType( NodeType.ELEMENT );
}
})
.setNamespaceAware( true )
.newDigester();
Element element = digester.parse( getInputStream( "Test10.xml" ) );
assertNotNull( element );
assertNotNull( element.getAttributeNodeNS( "http://commons.apache.org/digester/Bar", "test" ) );
assertEquals( "MyTestAttribute",
element.getAttributeNodeNS( "http://commons.apache.org/digester/Bar", "test" ).getNodeValue() );
assertEquals( "test",
element.getAttributeNodeNS( "http://commons.apache.org/digester/Bar", "test" ).getLocalName() );
assertEquals( "bar", element.getAttributeNodeNS( "http://commons.apache.org/digester/Bar", "test" ).getPrefix() );
assertEquals( "bar:test",
element.getAttributeNodeNS( "http://commons.apache.org/digester/Bar", "test" ).getName() );
}
/**
* Tests whether non-namespaced attributes are handled correctly, using the example from the file Test11 XML file.
*/
@Test
public void testNonNamespacedAttribute()
throws SAXException, IOException
{
Digester digester = newLoader( new AbstractRulesModule()
{
@Override
protected void configure()
{
forPattern( "employee" ).createNode().ofType( NodeType.ELEMENT );
}
})
.setNamespaceAware( true )
.newDigester();
Element element = digester.parse( getInputStream( "Test10.xml" ) );
assertNotNull( element );
assertNotNull( element.getAttributeNode( "firstName" ) );
assertEquals( "First Name", element.getAttributeNode( "firstName" ).getNodeValue() );
assertEquals( "firstName", element.getAttributeNode( "firstName" ).getLocalName() );
assertEquals( null, element.getAttributeNode( "firstName" ).getPrefix() );
assertEquals( "firstName", element.getAttributeNode( "firstName" ).getName() );
}
/**
* Tests whether the created fragment can be imported into an existing document.
*/
@Test
public void testImport()
throws SAXException, ParserConfigurationException, IOException
{
Digester digester = newLoader( new AbstractRulesModule()
{
@Override
protected void configure()
{
forPattern( "root" ).createNode().ofType( NodeType.DOCUMENT_FRAGMENT );
}
})
.newDigester();
DocumentFragment fragment = digester.parse( new StringReader( TEST_XML ) );
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.newDocument();
Node importedFragment = doc.importNode( fragment, true );
doc.appendChild( doc.createElement( "root" ) );
doc.getFirstChild().appendChild( importedFragment );
}
/**
* This unit test checks that text nodes are correctly created when xml entities are used. In particular, this
* usually causes the xml parser to make multiple invocations of the characters(..) sax callback, rather than just
* one.
*/
@Test
public void testEntityText()
throws Exception
{
String TEST_XML2 = "<?xml version='1.0'?><root><alpha>&#65; &#65;</alpha></root>";
Digester digester = newLoader( new AbstractRulesModule()
{
@Override
protected void configure()
{
forPattern( "root/alpha" ).createNode();
}
})
.newDigester();
Element element = digester.parse( new StringReader( TEST_XML2 ) );
assertNotNull( element );
assertEquals( "alpha", element.getNodeName() );
assertNull( element.getLocalName() );
assertNull( element.getNamespaceURI() );
assertEquals( 1, element.getChildNodes().getLength() );
assertEquals( "A A", element.getFirstChild().getNodeValue() );
}
// ------------------------------------------------ Utility Support Methods
/**
* Return an appropriate InputStream for the specified test file (which must be inside our current package.
*
* @param name Name of the test file we want
* @throws IOException if an input/output error occurs
*/
protected InputStream getInputStream( String name )
throws IOException
{
return ( this.getClass().getResourceAsStream( "/org/apache/commons/digester3/" + name ) );
}
}