001 /* 002 * Copyright 2004-2005 Stephen McConnell 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 013 * implied. 014 * 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 package net.dpml.util; 020 021 import java.io.File; 022 import java.io.FileNotFoundException; 023 import java.io.InputStream; 024 import java.util.ArrayList; 025 import java.util.Properties; 026 027 import javax.xml.parsers.DocumentBuilder; 028 import javax.xml.parsers.DocumentBuilderFactory; 029 030 import org.w3c.dom.Document; 031 import org.w3c.dom.Element; 032 import org.w3c.dom.Node; 033 import org.w3c.dom.NodeList; 034 035 /** 036 * Utility class supporting the translation of DOM content into local child, children, 037 * attribute and value values. 038 * 039 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a> 040 * @version 1.1.0 041 */ 042 public final class ElementHelper 043 { 044 private static final Resolver SIMPLE_RESOLVER = new SimpleResolver(); 045 046 private ElementHelper() 047 { 048 // utility class 049 } 050 051 /** 052 * Return the root element of the supplied file. 053 * @param definition the file to load 054 * @return the root element 055 * @exception Exception if the error occurs during root element establishment 056 */ 057 public static Element getRootElement( final File definition ) 058 throws Exception 059 { 060 if( !definition.exists() ) 061 { 062 throw new FileNotFoundException( definition.toString() ); 063 } 064 065 if( !definition.isFile() ) 066 { 067 final String error = 068 "Source is not a file: " + definition; 069 throw new IllegalArgumentException( error ); 070 } 071 072 final DocumentBuilderFactory factory = 073 DocumentBuilderFactory.newInstance(); 074 factory.setValidating( false ); 075 factory.setNamespaceAware( false ); 076 final Document document = 077 factory.newDocumentBuilder().parse( definition ); 078 return document.getDocumentElement(); 079 } 080 081 /** 082 * Return the root element of the supplied input stream. 083 * @param input the input stream containing a XML definition 084 * @return the root element 085 * @exception Exception if an error occurs 086 */ 087 public static Element getRootElement( final InputStream input ) 088 throws Exception 089 { 090 final DocumentBuilderFactory factory = 091 DocumentBuilderFactory.newInstance(); 092 factory.setValidating( false ); 093 factory.setNamespaceAware( false ); 094 factory.setExpandEntityReferences( false ); 095 DocumentBuilder builder = factory.newDocumentBuilder(); 096 return getRootElement( builder, input ); 097 } 098 099 /** 100 * Return the root element of the supplied input stream. 101 * @param builder the document builder 102 * @param input the input stream containing a XML definition 103 * @return the root element 104 * @exception Exception if an error occurs 105 */ 106 public static Element getRootElement( final DocumentBuilder builder, final InputStream input ) 107 throws Exception 108 { 109 final Document document = builder.parse( input ); 110 return document.getDocumentElement(); 111 } 112 113 /** 114 * Return a named child relative to a supplied element. 115 * @param root the parent DOM element 116 * @param name the name of a child element 117 * @return the child element of null if the child does not exist 118 */ 119 public static Element getChild( final Element root, final String name ) 120 { 121 if( null == root ) 122 { 123 return null; 124 } 125 Element[] children = getChildren( root ); 126 for( int i=0; i<children.length; i++ ) 127 { 128 Element child = children[i]; 129 if( name.equals( child.getTagName() ) ) 130 { 131 return child; 132 } 133 } 134 return null; 135 } 136 137 /** 138 * Return all children matching the supplied element name. 139 * @param root the parent DOM element 140 * @param name the name against which child element will be matched 141 * @return the array of child elements with a matching name 142 */ 143 public static Element[] getChildren( final Element root, final String name ) 144 { 145 if( null == root ) 146 { 147 return new Element[0]; 148 } 149 Element[] children = getChildren( root ); 150 final ArrayList result = new ArrayList(); 151 for( int i=0; i<children.length; i++ ) 152 { 153 final Element child = children[i]; 154 if( name.equals( child.getTagName() ) ) 155 { 156 result.add( child ); 157 } 158 } 159 return (Element[]) result.toArray( new Element[0] ); 160 } 161 162 /** 163 * Return all children of the supplied parent. 164 * @param root the parent DOM element 165 * @return the array of all children 166 */ 167 public static Element[] getChildren( final Element root ) 168 { 169 if( null == root ) 170 { 171 return new Element[0]; 172 } 173 final NodeList list = root.getChildNodes(); 174 final int n = list.getLength(); 175 if( n < 1 ) 176 { 177 return new Element[0]; 178 } 179 final ArrayList result = new ArrayList(); 180 for( int i=0; i < n; i++ ) 181 { 182 final Node item = list.item( i ); 183 if( item instanceof Element ) 184 { 185 result.add( item ); 186 } 187 } 188 return (Element[]) result.toArray( new Element[0] ); 189 } 190 191 /** 192 * Return the value of an element. 193 * @param node the DOM node 194 * @return the node value 195 */ 196 public static String getValue( final Element node ) 197 { 198 return getValue( node, null ); 199 } 200 201 /** 202 * Return the value of an element. 203 * @param node the DOM node 204 * @return the node value 205 */ 206 public static String getValue( final Element node, Resolver resolver ) 207 { 208 if( null == node ) 209 { 210 return null; 211 } 212 String value; 213 if( node.getChildNodes().getLength() > 0 ) 214 { 215 value = node.getFirstChild().getNodeValue(); 216 } 217 else 218 { 219 value = node.getNodeValue(); 220 } 221 return normalize( resolver, value ); 222 } 223 224 /** 225 * Return the value of an element attribute. 226 * @param node the DOM node 227 * @param key the attribute key 228 * @return the attribute value or null if the attribute is undefined 229 */ 230 public static String getAttribute( final Element node, final String key ) 231 { 232 return getAttribute( node, key, null ); 233 } 234 235 /** 236 * Return the value of an element attribute. 237 * @param node the DOM node 238 * @param key the attribute key 239 * @param def the default value if the attribute is undefined 240 * @return the attribute value or the default value if undefined 241 */ 242 public static String getAttribute( final Element node, final String key, final String def ) 243 { 244 return getAttribute( node, key, def, null ); 245 } 246 247 /** 248 * Return the value of an element attribute. 249 * @param node the DOM node 250 * @param key the attribute key 251 * @param def the default value if the attribute is undefined 252 * @return the attribute value or the default value if undefined 253 */ 254 public static String getAttribute( final Element node, final String key, final String def, Resolver resolver ) 255 { 256 if( null == node ) 257 { 258 return def; 259 } 260 if( !node.hasAttribute( key ) ) 261 { 262 return def; 263 } 264 String v = node.getAttribute( key ); 265 return normalize( resolver, v ); 266 } 267 268 /** 269 * Return the value of an element attribute as a boolean 270 * @param node the DOM node 271 * @param key the attribute key 272 * @return the attribute value as a boolean or false if undefined 273 */ 274 public static boolean getBooleanAttribute( final Element node, final String key ) 275 { 276 return getBooleanAttribute( node, key, false ); 277 } 278 279 /** 280 * Return the value of an element attribute as a boolean. 281 * @param node the DOM node 282 * @param key the attribute key 283 * @param def the default value if the attribute is undefined 284 * @return the attribute value or the default value if undefined 285 */ 286 public static boolean getBooleanAttribute( final Element node, final String key, final boolean def ) 287 { 288 return getBooleanAttribute( node, key, def, null ); 289 } 290 291 /** 292 * Return the value of an element attribute as a boolean. 293 * @param node the DOM node 294 * @param key the attribute key 295 * @param def the default value if the attribute is undefined 296 * @return the attribute value or the default value if undefined 297 */ 298 public static boolean getBooleanAttribute( 299 final Element node, final String key, final boolean def, Resolver resolver ) 300 { 301 if( null == node ) 302 { 303 return def; 304 } 305 306 if( !node.hasAttribute( key ) ) 307 { 308 return def; 309 } 310 311 String value = node.getAttribute( key ); 312 value = normalize( resolver, value ); 313 if( value.equals( "" ) ) 314 { 315 return def; 316 } 317 if( value.equalsIgnoreCase( "true" ) ) 318 { 319 return true; 320 } 321 if( value.equalsIgnoreCase( "false" ) ) 322 { 323 return false; 324 } 325 final String error = 326 "Boolean argument [" + value + "] not recognized."; 327 throw new IllegalArgumentException( error ); 328 } 329 330 /** 331 * Parse the value for any property tokens relative to system properties. 332 * @param value the value to parse 333 * @return the normalized string 334 */ 335 static String normalize( String value ) 336 { 337 return SIMPLE_RESOLVER.resolve( value ); 338 } 339 340 /** 341 * Parse the value for any property tokens relative to system properties. 342 * @param value the value to parse 343 * @return the normalized string 344 */ 345 static String normalize( Resolver resolver, String value ) 346 { 347 if( null != resolver ) 348 { 349 return resolver.resolve( value ); 350 } 351 else 352 { 353 return value; 354 } 355 } 356 357 /** 358 * Parse the value for any property tokens relative to the supplied properties. 359 * @param value the value to parse 360 * @param props the reference properties 361 * @return the normalized string 362 */ 363 static String normalize( String value, Properties props ) 364 { 365 return PropertyResolver.resolve( props, value ); 366 } 367 }