View Javadoc

1   /* $Id: NodeCreateRuleTestCase.java 1212599 2011-12-09 19:46:42Z simonetripodi $
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one or more
4    * contributor license agreements.  See the NOTICE file distributed with
5    * this work for additional information regarding copyright ownership.
6    * The ASF licenses this file to You under the Apache License, Version 2.0
7    * (the "License"); you may not use this file except in compliance with
8    * the License.  You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.commons.digester3;
20  
21  import static org.apache.commons.digester3.binder.DigesterLoader.newLoader;
22  import static org.junit.Assert.assertEquals;
23  import static org.junit.Assert.assertNotNull;
24  import static org.junit.Assert.assertNull;
25  import static org.junit.Assert.assertTrue;
26  import static org.junit.Assert.fail;
27  
28  import java.io.IOException;
29  import java.io.InputStream;
30  import java.io.StringReader;
31  import java.util.ArrayList;
32  import java.util.List;
33  
34  import javax.xml.parsers.DocumentBuilder;
35  import javax.xml.parsers.DocumentBuilderFactory;
36  import javax.xml.parsers.ParserConfigurationException;
37  
38  import org.apache.commons.digester3.binder.AbstractRulesModule;
39  import org.apache.commons.digester3.binder.NodeCreateRuleProvider.NodeType;
40  import org.junit.Test;
41  import org.w3c.dom.Document;
42  import org.w3c.dom.DocumentFragment;
43  import org.w3c.dom.Element;
44  import org.w3c.dom.Node;
45  import org.xml.sax.SAXException;
46  
47  /**
48   * <p>
49   * Test case for the <code>NodeCreateRule</code>.
50   *
51   * @author Christopher Lenz
52   */
53  public class NodeCreateRuleTestCase
54  {
55  
56      // ----------------------------------------------------- Instance Variables
57  
58      /**
59       * Simple test xml document used in the tests.
60       */
61      protected final static String TEST_XML = "<?xml version='1.0'?><root>ROOT BODY<alpha>ALPHA BODY</alpha>"
62          + "<beta>BETA BODY</beta><gamma>GAMMA BODY</gamma></root>";
63  
64      // ------------------------------------------------ Individual Test Methods
65  
66      /**
67       * Tests simple element construction, using the {@link #TEST_XML} XML input data.
68       */
69      @Test
70      public void testInvalidNodeTypes()
71          throws Exception
72      {
73  
74          try
75          {
76              Rule rule = new NodeCreateRule( Node.ATTRIBUTE_NODE );
77              fail( "IllegalArgumentException expected for type ATTRIBUTE_NODE" );
78              assertNotNull( rule ); // just to prevent compiler warning on unused var
79          }
80          catch ( IllegalArgumentException iae )
81          {
82              // expected
83          }
84          try
85          {
86              Rule rule = new NodeCreateRule( Node.CDATA_SECTION_NODE );
87              fail( "IllegalArgumentException expected for type " + "CDATA_SECTION_NODE" );
88              assertNotNull( rule ); // just to prevent compiler warning on unused var
89          }
90          catch ( IllegalArgumentException iae )
91          {
92              // expected
93          }
94          try
95          {
96              Rule rule = new NodeCreateRule( Node.COMMENT_NODE );
97              fail( "IllegalArgumentException expected for type COMMENT_NODE" );
98              assertNotNull( rule ); // just to prevent compiler warning on unused var
99          }
100         catch ( IllegalArgumentException iae )
101         {
102             // expected
103         }
104         try
105         {
106             Rule rule = new NodeCreateRule( Node.DOCUMENT_NODE );
107             fail( "IllegalArgumentException expected for type DOCUMENT_NODE" );
108             assertNotNull( rule ); // just to prevent compiler warning on unused var
109         }
110         catch ( IllegalArgumentException iae )
111         {
112             // expected
113         }
114         try
115         {
116             Rule rule = new NodeCreateRule( Node.DOCUMENT_TYPE_NODE );
117             fail( "IllegalArgumentException expected for type " + "DOCUMENT_TYPE_NODE" );
118             assertNotNull( rule ); // just to prevent compiler warning on unused var
119         }
120         catch ( IllegalArgumentException iae )
121         {
122             // expected
123         }
124         try
125         {
126             Rule rule = new NodeCreateRule( Node.ENTITY_NODE );
127             fail( "IllegalArgumentException expected for type ENTITY_NODE" );
128             assertNotNull( rule ); // just to prevent compiler warning on unused var
129         }
130         catch ( IllegalArgumentException iae )
131         {
132             // expected
133         }
134         try
135         {
136             Rule rule = new NodeCreateRule( Node.ENTITY_REFERENCE_NODE );
137             fail( "IllegalArgumentException expected for type " + "ENTITY_REFERENCE_NODE" );
138             assertNotNull( rule ); // just to prevent compiler warning on unused var
139         }
140         catch ( IllegalArgumentException iae )
141         {
142             // expected
143         }
144         try
145         {
146             Rule rule = new NodeCreateRule( Node.NOTATION_NODE );
147             fail( "IllegalArgumentException expected for type NOTATION_NODE" );
148             assertNotNull( rule ); // just to prevent compiler warning on unused var
149         }
150         catch ( IllegalArgumentException iae )
151         {
152             // expected
153         }
154         try
155         {
156             Rule rule = new NodeCreateRule( Node.PROCESSING_INSTRUCTION_NODE );
157             fail( "IllegalArgumentException expected for type " + "PROCESSING_INSTRUCTION_NODE" );
158             assertNotNull( rule ); // just to prevent compiler warning on unused var
159         }
160         catch ( IllegalArgumentException iae )
161         {
162             // expected
163         }
164         try
165         {
166             Rule rule = new NodeCreateRule( Node.TEXT_NODE );
167             fail( "IllegalArgumentException expected for type TEXT_NODE" );
168             assertNotNull( rule ); // just to prevent compiler warning on unused var
169         }
170         catch ( IllegalArgumentException iae )
171         {
172             // expected
173         }
174 
175     }
176 
177     /**
178      * Tests simple element construction, using the {@link #TEST_XML} XML input data.
179      */
180     @Test
181     public void testElement()
182         throws SAXException, IOException
183     {
184         Digester digester = newLoader( new AbstractRulesModule()
185         {
186 
187             @Override
188             protected void configure()
189             {
190                 forPattern( "root/alpha" ).createNode();
191             }
192 
193         }).newDigester();
194 
195         Element element = digester.parse( new StringReader( TEST_XML ) );
196 
197         assertNotNull( element );
198         assertEquals( "alpha", element.getNodeName() );
199         assertNull( element.getLocalName() );
200         assertNull( element.getNamespaceURI() );
201         assertEquals( 1, element.getChildNodes().getLength() );
202         assertEquals( "ALPHA BODY", element.getFirstChild().getNodeValue() );
203 
204     }
205 
206     /**
207      * Tests simple fragment construction, using the {@link #TEST_XML} XML input data.
208      */
209     @Test
210     public void testDocumentFragment()
211         throws SAXException, IOException
212     {
213         Digester digester = newLoader( new AbstractRulesModule()
214         {
215 
216             @Override
217             protected void configure()
218             {
219                 forPattern( "root" ).createNode().ofType( NodeType.DOCUMENT_FRAGMENT );
220             }
221 
222         }).newDigester();
223 
224         DocumentFragment fragment = digester.parse( new StringReader( TEST_XML ) );
225 
226         assertNotNull( fragment );
227         assertEquals( 4, fragment.getChildNodes().getLength() );
228 
229         Node rootBody = fragment.getFirstChild();
230         assertEquals( Node.TEXT_NODE, rootBody.getNodeType() );
231         assertEquals( "ROOT BODY", rootBody.getNodeValue() );
232 
233         Node alpha = fragment.getChildNodes().item( 1 );
234         assertEquals( Node.ELEMENT_NODE, alpha.getNodeType() );
235         assertEquals( "alpha", alpha.getNodeName() );
236         assertNull( ( (Element) alpha ).getLocalName() );
237         assertNull( ( (Element) alpha ).getNamespaceURI() );
238         assertEquals( 1, alpha.getChildNodes().getLength() );
239         assertEquals( "ALPHA BODY", alpha.getFirstChild().getNodeValue() );
240 
241         Node beta = fragment.getChildNodes().item( 2 );
242         assertEquals( Node.ELEMENT_NODE, beta.getNodeType() );
243         assertEquals( "beta", beta.getNodeName() );
244         assertNull( ( (Element) beta ).getLocalName() );
245         assertNull( ( (Element) beta ).getNamespaceURI() );
246         assertEquals( 1, beta.getChildNodes().getLength() );
247         assertEquals( "BETA BODY", beta.getFirstChild().getNodeValue() );
248 
249         Node gamma = fragment.getChildNodes().item( 3 );
250         assertEquals( Node.ELEMENT_NODE, gamma.getNodeType() );
251         assertEquals( "gamma", gamma.getNodeName() );
252         assertNull( ( (Element) gamma ).getLocalName() );
253         assertNull( ( (Element) gamma ).getNamespaceURI() );
254         assertEquals( 1, gamma.getChildNodes().getLength() );
255         assertEquals( "GAMMA BODY", gamma.getFirstChild().getNodeValue() );
256 
257     }
258 
259     /**
260      * Tests whether control is returned to digester after fragment construction.
261      */
262     @Test
263     public void testNested()
264         throws SAXException, IOException
265     {
266         Digester digester = newLoader( new AbstractRulesModule()
267         {
268 
269             @Override
270             protected void configure()
271             {
272                 forPattern( "root" ).createObject().ofType( ArrayList.class );
273                 forPattern( "root/a/b" ).createNode().ofType( NodeType.DOCUMENT_FRAGMENT )
274                     .then()
275                     .setRoot( "add" );
276                 forPattern( "root/b" ).createObject().ofType( String.class )
277                     .then()
278                     .setRoot( "add" );
279             }
280 
281         }).newDigester();
282 
283         List<?> list = digester.parse( getInputStream( "Test4.xml" ) );
284 
285         assertNotNull( list );
286         assertEquals( 2, list.size() );
287 
288         assertTrue( list.get( 0 ) instanceof DocumentFragment );
289         DocumentFragment fragment = (DocumentFragment) list.get( 0 );
290 
291         assertEquals( Node.ELEMENT_NODE, fragment.getFirstChild().getNodeType() );
292         Element a = (Element) fragment.getFirstChild();
293         assertEquals( "a", a.getNodeName() );
294         assertEquals( 1, a.getAttributes().getLength() );
295         assertEquals( "THREE", a.getAttribute( "name" ) );
296 
297         assertTrue( list.get( 1 ) instanceof String );
298 
299     }
300 
301     /**
302      * Tests whether attributes are correctly imported into the fragment, using the example in the Test1 XML file.
303      */
304     @Test
305     public void testAttributes()
306         throws SAXException, IOException
307     {
308         Digester digester = newLoader( new AbstractRulesModule()
309         {
310 
311             @Override
312             protected void configure()
313             {
314                 forPattern( "employee" ).createNode().ofType( NodeType.DOCUMENT_FRAGMENT );
315             }
316 
317         }).newDigester();
318 
319         DocumentFragment fragment = digester.parse( getInputStream( "Test1.xml" ) );
320 
321         assertNotNull( fragment );
322         assertEquals( 2, fragment.getChildNodes().getLength() );
323 
324         assertEquals( Node.ELEMENT_NODE, fragment.getFirstChild().getNodeType() );
325         Element address1 = (Element) fragment.getFirstChild();
326         assertEquals( "address", address1.getNodeName() );
327         assertEquals( 5, address1.getAttributes().getLength() );
328         assertEquals( "home", address1.getAttribute( "type" ) );
329         assertEquals( "Home Street", address1.getAttribute( "street" ) );
330         assertEquals( "Home City", address1.getAttribute( "city" ) );
331         assertEquals( "HS", address1.getAttribute( "state" ) );
332         assertEquals( "HmZip", address1.getAttribute( "zipCode" ) );
333 
334         assertEquals( Node.ELEMENT_NODE, fragment.getLastChild().getNodeType() );
335         Element address2 = (Element) fragment.getLastChild();
336         assertEquals( "address", address2.getNodeName() );
337         assertEquals( 5, address2.getAttributes().getLength() );
338         assertEquals( "office", address2.getAttribute( "type" ) );
339         assertEquals( "Office Street", address2.getAttribute( "street" ) );
340         assertEquals( "Office City", address2.getAttribute( "city" ) );
341         assertEquals( "OS", address2.getAttribute( "state" ) );
342         assertEquals( "OfZip", address2.getAttribute( "zipCode" ) );
343 
344     }
345 
346     /**
347      * Tests whether namespaces are handled correctly, using the example from the file Test3 XML file.
348      */
349     @Test
350     public void testNamespaces()
351         throws SAXException, IOException
352     {
353         Digester digester = newLoader( new AbstractRulesModule()
354         {
355 
356             @Override
357             protected void configure()
358             {
359                 forPattern( "employee" ).createNode().ofType( NodeType.DOCUMENT_FRAGMENT );
360             }
361 
362         })
363         .setNamespaceAware( true )
364         .newDigester();
365 
366         DocumentFragment fragment = digester.parse( getInputStream( "Test3.xml" ) );
367 
368         assertNotNull( fragment );
369         assertEquals( 2, fragment.getChildNodes().getLength() );
370 
371         assertEquals( Node.ELEMENT_NODE, fragment.getFirstChild().getNodeType() );
372         Element address1 = (Element) fragment.getFirstChild();
373         assertEquals( "address", address1.getNodeName() );
374         assertEquals( "http://commons.apache.org/digester/Bar", address1.getNamespaceURI() );
375         assertEquals( "address", address1.getLocalName() );
376         assertEquals( 5, address1.getAttributes().getLength() );
377         assertEquals( "home", address1.getAttribute( "type" ) );
378         assertEquals( "Home Street", address1.getAttribute( "street" ) );
379         assertEquals( "Home City", address1.getAttribute( "city" ) );
380         assertEquals( "HS", address1.getAttribute( "state" ) );
381         assertEquals( "HmZip", address1.getAttribute( "zipCode" ) );
382 
383         assertEquals( Node.ELEMENT_NODE, fragment.getLastChild().getNodeType() );
384         Element address2 = (Element) fragment.getLastChild();
385         assertEquals( "address", address2.getNodeName() );
386         assertEquals( "http://commons.apache.org/digester/Bar", address2.getNamespaceURI() );
387         assertEquals( "address", address2.getLocalName() );
388         assertEquals( 5, address2.getAttributes().getLength() );
389         assertEquals( "office", address2.getAttribute( "type" ) );
390         assertEquals( "Office Street", address2.getAttribute( "street" ) );
391         assertEquals( "Office City", address2.getAttribute( "city" ) );
392         assertEquals( "OS", address2.getAttribute( "state" ) );
393         assertEquals( "OfZip", address2.getAttribute( "zipCode" ) );
394 
395     }
396 
397     /**
398      * Tests whether namespaced attributes are handled correctly, using the example from the file Test10 XML file.
399      */
400     @Test
401     public void testNamespacedAttribute()
402         throws SAXException, IOException
403     {
404         Digester digester = newLoader( new AbstractRulesModule()
405         {
406 
407             @Override
408             protected void configure()
409             {
410                 forPattern( "employee" ).createNode().ofType( NodeType.ELEMENT );
411             }
412 
413         })
414         .setNamespaceAware( true )
415         .newDigester();
416 
417         Element element = digester.parse( getInputStream( "Test10.xml" ) );
418 
419         assertNotNull( element );
420 
421         assertNotNull( element.getAttributeNodeNS( "http://commons.apache.org/digester/Bar", "test" ) );
422         assertEquals( "MyTestAttribute",
423                       element.getAttributeNodeNS( "http://commons.apache.org/digester/Bar", "test" ).getNodeValue() );
424         assertEquals( "test",
425                       element.getAttributeNodeNS( "http://commons.apache.org/digester/Bar", "test" ).getLocalName() );
426         assertEquals( "bar", element.getAttributeNodeNS( "http://commons.apache.org/digester/Bar", "test" ).getPrefix() );
427         assertEquals( "bar:test",
428                       element.getAttributeNodeNS( "http://commons.apache.org/digester/Bar", "test" ).getName() );
429 
430     }
431 
432     /**
433      * Tests whether non-namespaced attributes are handled correctly, using the example from the file Test11 XML file.
434      */
435     @Test
436     public void testNonNamespacedAttribute()
437         throws SAXException, IOException
438     {
439         Digester digester = newLoader( new AbstractRulesModule()
440         {
441 
442             @Override
443             protected void configure()
444             {
445                 forPattern( "employee" ).createNode().ofType( NodeType.ELEMENT );
446             }
447 
448         })
449         .setNamespaceAware( true )
450         .newDigester();
451 
452         Element element = digester.parse( getInputStream( "Test10.xml" ) );
453 
454         assertNotNull( element );
455 
456         assertNotNull( element.getAttributeNode( "firstName" ) );
457         assertEquals( "First Name", element.getAttributeNode( "firstName" ).getNodeValue() );
458         assertEquals( "firstName", element.getAttributeNode( "firstName" ).getLocalName() );
459         assertEquals( null, element.getAttributeNode( "firstName" ).getPrefix() );
460         assertEquals( "firstName", element.getAttributeNode( "firstName" ).getName() );
461 
462     }
463 
464     /**
465      * Tests whether the created fragment can be imported into an existing document.
466      */
467     @Test
468     public void testImport()
469         throws SAXException, ParserConfigurationException, IOException
470     {
471         Digester digester = newLoader( new AbstractRulesModule()
472         {
473 
474             @Override
475             protected void configure()
476             {
477                 forPattern( "root" ).createNode().ofType( NodeType.DOCUMENT_FRAGMENT );
478             }
479 
480         })
481         .newDigester();
482 
483         DocumentFragment fragment = digester.parse( new StringReader( TEST_XML ) );
484 
485         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
486         DocumentBuilder builder = factory.newDocumentBuilder();
487         Document doc = builder.newDocument();
488         Node importedFragment = doc.importNode( fragment, true );
489         doc.appendChild( doc.createElement( "root" ) );
490         doc.getFirstChild().appendChild( importedFragment );
491 
492     }
493 
494     /**
495      * This unit test checks that text nodes are correctly created when xml entities are used. In particular, this
496      * usually causes the xml parser to make multiple invocations of the characters(..) sax callback, rather than just
497      * one.
498      */
499     @Test
500     public void testEntityText()
501         throws Exception
502     {
503         String TEST_XML2 = "<?xml version='1.0'?><root><alpha>&#65; &#65;</alpha></root>";
504 
505         Digester digester = newLoader( new AbstractRulesModule()
506         {
507 
508             @Override
509             protected void configure()
510             {
511                 forPattern( "root/alpha" ).createNode();
512             }
513 
514         })
515         .newDigester();
516 
517         Element element = digester.parse( new StringReader( TEST_XML2 ) );
518 
519         assertNotNull( element );
520         assertEquals( "alpha", element.getNodeName() );
521         assertNull( element.getLocalName() );
522         assertNull( element.getNamespaceURI() );
523         assertEquals( 1, element.getChildNodes().getLength() );
524         assertEquals( "A A", element.getFirstChild().getNodeValue() );
525     }
526 
527     // ------------------------------------------------ Utility Support Methods
528 
529     /**
530      * Return an appropriate InputStream for the specified test file (which must be inside our current package.
531      *
532      * @param name Name of the test file we want
533      * @exception IOException if an input/output error occurs
534      */
535     protected InputStream getInputStream( String name )
536         throws IOException
537     {
538 
539         return ( this.getClass().getResourceAsStream( "/org/apache/commons/digester3/" + name ) );
540 
541     }
542 
543 }