View Javadoc
1 /* 2 * Copyright (C) The JContainer Group. All rights reserved. 3 * 4 * This software is published under the terms of the JContainer 5 * Software License version 1.1, a copy of which has been included 6 * with this distribution in the LICENSE.txt file. 7 */ 8 package org.jcontainer.dna.impl; 9 10 import java.util.ArrayList; 11 import java.util.List; 12 import org.jcontainer.dna.Configuration; 13 import org.xml.sax.Attributes; 14 import org.xml.sax.Locator; 15 import org.xml.sax.SAXException; 16 import org.xml.sax.SAXParseException; 17 import org.xml.sax.helpers.DefaultHandler; 18 19 /*** 20 * The SAXConfigurationHandler builds a Configuration tree 21 * from SAX events. 22 * 23 * @author <a href="mailto:peter at realityforge.org">Peter Donald</a> 24 * @version $Revision: 1.21 $ $Date: 2003/10/05 09:04:55 $ 25 */ 26 public class SAXConfigurationHandler 27 extends DefaultHandler 28 { 29 /*** 30 * Empty string used for padding out contents array. 31 */ 32 private static final String EMPTY_STRING = ""; 33 34 /*** 35 * Constant to indicate location of 36 * element when parser does not support Locator 37 * interface. 38 */ 39 private static final String UNKNOWN = ""; 40 41 /*** 42 * Stack of configuration elements currently being 43 * constructed. 44 */ 45 private final List m_elements = new ArrayList(); 46 47 /*** 48 * Stakc of content text for elements currently being 49 * constructed. 50 */ 51 private final ArrayList m_values = new ArrayList(); 52 53 /*** 54 * The configuration element created. 55 */ 56 private Configuration m_configuration; 57 58 /*** 59 * The Locator specified by XML parser. 60 */ 61 private Locator m_locator; 62 63 /*** 64 * Let the XML parser specify locator for when 65 * events arrive at handler. 66 * 67 * @param locator the locator 68 */ 69 public void setDocumentLocator( final Locator locator ) 70 { 71 m_locator = locator; 72 } 73 74 /*** 75 * Reset internal state of handler in preapration for reuse. 76 */ 77 public void clear() 78 { 79 m_elements.clear(); 80 m_values.clear(); 81 m_locator = null; 82 } 83 84 /*** 85 * Return the configuration created by handler. 86 * 87 * @return the configuration created by handler. 88 */ 89 public Configuration getConfiguration() 90 { 91 return m_configuration; 92 } 93 94 /*** 95 * Start an element and thus a Configuration object. 96 * 97 * @param uri the uri (ignored) 98 * @param localName the localName (ignored) 99 * @param qName the qualified name (used for name of configuration) 100 * @param attributes the attributes of XML element 101 * @throws SAXException if unable to parse element 102 */ 103 public void startElement( final String uri, 104 final String localName, 105 final String qName, 106 final Attributes attributes ) 107 throws SAXException 108 { 109 DefaultConfiguration parent = null; 110 String path = ConfigurationUtil.ROOT_PATH; 111 if( m_elements.size() > 0 ) 112 { 113 final int index = m_elements.size() - 1; 114 parent = 115 (DefaultConfiguration)m_elements.get( index ); 116 path = ConfigurationUtil. 117 generatePathName( parent.getPath(), 118 parent.getName() ); 119 } 120 final DefaultConfiguration configuration = 121 new DefaultConfiguration( qName, getLocationDescription(), path ); 122 if( null != parent ) 123 { 124 parent.addChild( configuration ); 125 } 126 final int length = attributes.getLength(); 127 for( int i = 0; i < length; i++ ) 128 { 129 final String key = attributes.getQName( i ); 130 final String value = attributes.getValue( i ); 131 final String newValue = 132 processAttributeText( configuration, key, value ); 133 configuration.setAttribute( key, newValue ); 134 } 135 136 m_elements.add( configuration ); 137 } 138 139 /*** 140 * End an element and thus a Configuration object. 141 * Will pop of configuration and value of object from 142 * stack. If the handler detects that element has both 143 * child elements and a text value then it will throw 144 * a SAXException. 145 * 146 * @param uri the uri (ignored) 147 * @param localName the localName (ignored) 148 * @param qName the qualified name (used for name of configuration) 149 * @throws SAXException if element had mixed content 150 */ 151 public void endElement( final String uri, 152 final String localName, 153 final String qName ) 154 throws SAXException 155 { 156 final int index = m_elements.size() - 1; 157 final DefaultConfiguration configuration = 158 (DefaultConfiguration)m_elements.remove( index ); 159 if( index < m_values.size() ) 160 { 161 final String value = m_values.remove( index ).toString(); 162 if( 0 != value.trim().length() ) 163 { 164 if( 0 == configuration.getChildren().length ) 165 { 166 final String newValue = 167 processValueText( configuration, value ); 168 configuration.setValue( newValue ); 169 } 170 else 171 { 172 final String message = 173 "Mixed content (" + value.trim() + ") " + 174 "not supported @ " + getLocationDescription(); 175 throw new SAXException( message ); 176 } 177 } 178 } 179 m_configuration = configuration; 180 } 181 182 /*** 183 * Receive text data for current element. 184 * 185 * @param ch the char array 186 * @param start the start index 187 * @param length the length of data 188 * @throws SAXException if unable ot parse data 189 */ 190 public void characters( final char[] ch, 191 final int start, 192 final int length ) 193 throws SAXException 194 { 195 final int index = m_elements.size() - 1; 196 StringBuffer sb = null; 197 if( index < m_values.size() ) 198 { 199 sb = (StringBuffer)m_values.get( index ); 200 } 201 if( null == sb ) 202 { 203 sb = new StringBuffer(); 204 final int minCapacity = index + 1; 205 m_values.ensureCapacity( minCapacity ); 206 final int size = m_values.size(); 207 for( int i = size; i < minCapacity; i++ ) 208 { 209 m_values.add( EMPTY_STRING ); 210 } 211 m_values.set( index, sb ); 212 } 213 sb.append( ch, start, length ); 214 } 215 216 /*** 217 * Rethrow exception and dont attempt to do 218 * any error handling. 219 * 220 * @param spe the input exception 221 * @throws SAXException always thrown 222 */ 223 public void warning( final SAXParseException spe ) 224 throws SAXException 225 { 226 throw spe; 227 } 228 229 /*** 230 * Rethrow exception and dont attempt to do 231 * any error handling. 232 * 233 * @param spe the input exception 234 * @throws SAXException always thrown 235 */ 236 public void error( final SAXParseException spe ) 237 throws SAXException 238 { 239 throw spe; 240 } 241 242 /*** 243 * Rethrow exception and dont attempt to do 244 * any error handling. 245 * 246 * @param spe the input exception 247 * @throws SAXException always thrown 248 */ 249 public void fatalError( final SAXParseException spe ) 250 throws SAXException 251 { 252 throw spe; 253 } 254 255 /*** 256 * Utility method to derive current location of 257 * XML parser. Attempts to build up a string containing 258 * systemID:lineNumber:columnNumber such as 259 * "file.xml:20:3" if parser supports all fields. 260 * 261 * @return the location description 262 */ 263 protected final String getLocationDescription() 264 { 265 if( null == m_locator || 266 null == m_locator.getSystemId() ) 267 { 268 return UNKNOWN; 269 } 270 else if( -1 == m_locator.getLineNumber() ) 271 { 272 return m_locator.getSystemId(); 273 } 274 else if( -1 == m_locator.getColumnNumber() ) 275 { 276 return m_locator.getSystemId() + ":" + 277 m_locator.getLineNumber(); 278 } 279 else 280 { 281 return m_locator.getSystemId() + ':' + 282 m_locator.getLineNumber() + ':' + 283 m_locator.getColumnNumber(); 284 } 285 } 286 287 /*** 288 * Users may subclass this method to process attribute 289 * prior to it being set. 290 * 291 * @param configuration the associated configuration 292 * @param name the attribute name 293 * @param value the attribute value 294 * @return the attribute value 295 */ 296 protected String processAttributeText( final Configuration configuration, 297 final String name, 298 final String value ) 299 { 300 return value; 301 } 302 303 /*** 304 * Users may subclass this method to process content 305 * prior to it being set. 306 * 307 * @param configuration the associated configuration 308 * @param value the value 309 * @return the value 310 */ 311 protected String processValueText( final Configuration configuration, 312 final String value ) 313 { 314 return value; 315 } 316 }

This page was automatically generated by Maven