001/* $Id: LocationTrackerTestCase.java 1125368 2011-05-20 13:06:27Z simonetripodi $
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one or more
004 * contributor license agreements.  See the NOTICE file distributed with
005 * this work for additional information regarding copyright ownership.
006 * The ASF licenses this file to You under the Apache License, Version 2.0
007 * (the "License"); you may not use this file except in compliance with
008 * the License.  You may obtain a copy of the License at
009 *
010 *      http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.commons.digester3;
020
021import static org.apache.commons.digester3.binder.DigesterLoader.newLoader;
022
023import static org.junit.Assert.assertEquals;
024import static org.junit.Assert.assertNotNull;
025
026import java.io.StringReader;
027import java.util.HashMap;
028import java.util.List;
029import java.util.Map;
030
031import org.apache.commons.digester3.Digester;
032import org.apache.commons.digester3.StackAction;
033import org.apache.commons.digester3.binder.AbstractRulesModule;
034import org.junit.Test;
035import org.xml.sax.Locator;
036
037/**
038 * Tests that StackAction can be used to track the source location of objects created from input xml stream.
039 */
040
041public class LocationTrackerTestCase
042{
043
044    private static class LocationTracker
045        implements StackAction
046    {
047        public Map<Object, String> locations = new HashMap<Object, String>();
048
049        public <T> T onPush( Digester d, String stackName, T o )
050        {
051            if ( stackName == null )
052            {
053                // we only care about the real object stack
054
055                // note that a Locator object can also provide
056                // publicId and systemId info.
057                Locator l = d.getDocumentLocator();
058                StringBuilder locn = new StringBuilder();
059                locn.append( "line=" );
060                locn.append( l.getLineNumber() );
061                locations.put( o, locn.toString() );
062            }
063            return o;
064        }
065
066        public <T> T onPop( Digester d, String stackName, T o )
067        {
068            return o;
069        }
070    }
071
072    @Test
073    public void testAll()
074        throws Exception
075    {
076        final String TEST_XML =
077            "<?xml version='1.0'?>\n" + "<box id='root'>\n" + "  <subBox id='box1'/>\n" + "  <ignoreme/>\n"
078                + "  <subBox id='box2'/> <subBox id='box3'/>\n" + "</box>";
079
080        LocationTracker locnTracker = new LocationTracker();
081
082        Digester digester = newLoader( new AbstractRulesModule()
083        {
084
085            @Override
086            protected void configure()
087            {
088                forPattern( "box" ).createObject().ofType( Box.class )
089                    .then()
090                    .setProperties();
091                forPattern( "box/subBox" ).createObject().ofType( Box.class )
092                    .then()
093                    .setProperties()
094                    .then()
095                    .setNext( "addChild" );
096            }
097
098        })
099        .setStackAction( locnTracker )
100        .newDigester();
101
102        Box root = digester.parse( new StringReader( TEST_XML ) );
103        assertNotNull( root );
104        List<Box> children = root.getChildren();
105        assertEquals( 3, children.size() );
106        Box box1 = children.get( 0 );
107        Box box2 = children.get( 1 );
108        Box box3 = children.get( 2 );
109
110        assertEquals( "line=2", locnTracker.locations.get( root ) );
111        assertEquals( "line=3", locnTracker.locations.get( box1 ) );
112        assertEquals( "line=5", locnTracker.locations.get( box2 ) );
113        assertEquals( "line=5", locnTracker.locations.get( box3 ) );
114    }
115}