1 package org.apache.commons.betwixt.digester; 2 17 import java.beans.PropertyDescriptor ; 18 import java.lang.reflect.Method ; 19 import java.util.Map ; 20 21 import org.apache.commons.betwixt.ElementDescriptor; 22 import org.apache.commons.betwixt.XMLBeanInfo; 23 import org.apache.commons.betwixt.XMLUtils; 24 import org.apache.commons.betwixt.expression.ConstantExpression; 25 import org.apache.commons.betwixt.expression.IteratorExpression; 26 import org.apache.commons.betwixt.expression.MethodExpression; 27 import org.apache.commons.betwixt.expression.MethodUpdater; 28 import org.apache.commons.logging.Log; 29 import org.apache.commons.logging.LogFactory; 30 import org.xml.sax.Attributes ; 31 import org.xml.sax.SAXException ; 32 33 39 public class ElementRule extends MappedPropertyRule { 40 41 42 private static Log log = LogFactory.getLog( ElementRule.class ); 43 49 public static final void setLog(Log newLog) { 50 log = newLog; 51 } 52 53 54 private Class beanClass; 55 56 public ElementRule() {} 57 58 61 70 public void begin(String name, String namespace, Attributes attributes) throws SAXException { 71 String nameAttributeValue = attributes.getValue( "name" ); 72 73 if ( nameAttributeValue == null || nameAttributeValue.trim().equals( "" ) ) { 75 throw new SAXException ("Name attribute is required."); 76 } 77 78 if ( !XMLUtils.isWellFormedXMLName( nameAttributeValue ) ) { 80 throw new SAXException ("'" + nameAttributeValue + "' would not be a well formed xml element name."); 81 } 82 83 ElementDescriptor descriptor = new ElementDescriptor(); 84 descriptor.setLocalName( nameAttributeValue ); 85 String uri = attributes.getValue( "uri" ); 86 String qName = nameAttributeValue; 87 if ( uri != null ) { 88 descriptor.setURI( uri ); 89 String prefix = getXMLIntrospector().getConfiguration().getPrefixMapper().getPrefix(uri); 90 qName = prefix + ":" + nameAttributeValue; 91 } 92 descriptor.setQualifiedName( qName ); 93 94 String propertyName = attributes.getValue( "property" ); 95 descriptor.setPropertyName( propertyName ); 96 97 String propertyType = attributes.getValue( "type" ); 98 99 if (log.isTraceEnabled()) { 100 log.trace( 101 "(BEGIN) name=" + nameAttributeValue + " uri=" + uri 102 + " property=" + propertyName + " type=" + propertyType); 103 } 104 105 descriptor.setPropertyType( 107 getPropertyType( propertyType, beanClass, propertyName ) 108 ); 109 110 String implementationClass = attributes.getValue( "class" ); 111 if ( log.isTraceEnabled() ) { 112 log.trace("'class' attribute=" + implementationClass); 113 } 114 if ( implementationClass != null ) { 115 try { 116 117 Class clazz = Class.forName(implementationClass); 118 descriptor.setImplementationClass( clazz ); 119 120 } catch (Exception e) { 121 if ( log.isDebugEnabled() ) { 122 log.debug("Cannot load class named: " + implementationClass, e); 123 } 124 throw new SAXException ("Cannot load class named: " + implementationClass); 125 } 126 } 127 128 if ( propertyName != null && propertyName.length() > 0 ) { 129 configureDescriptor(descriptor, attributes.getValue( "updater" )); 130 131 } else { 132 String value = attributes.getValue( "value" ); 133 if ( value != null ) { 134 descriptor.setTextExpression( new ConstantExpression( value ) ); 135 } 136 } 137 138 Object top = digester.peek(); 139 if ( top instanceof XMLBeanInfo ) { 140 XMLBeanInfo beanInfo = (XMLBeanInfo) top; 141 beanInfo.setElementDescriptor( descriptor ); 142 beanClass = beanInfo.getBeanClass(); 143 descriptor.setPropertyType( beanClass ); 144 145 } else if ( top instanceof ElementDescriptor ) { 146 ElementDescriptor parent = (ElementDescriptor) top; 147 parent.addElementDescriptor( descriptor ); 148 149 } else { 150 throw new SAXException ( "Invalid use of <element>. It should " 151 + "be nested inside <info> or other <element> nodes" ); 152 } 153 154 digester.push(descriptor); 155 } 156 157 158 161 public void end(String name, String namespace) { 162 Object top = digester.pop(); 163 } 164 165 166 169 176 protected void configureDescriptor(ElementDescriptor elementDescriptor) { 177 configureDescriptor( elementDescriptor, null ); 178 } 179 180 188 protected void configureDescriptor( 189 ElementDescriptor elementDescriptor, 190 String updateMethodName) { 191 Class beanClass = getBeanClass(); 192 if ( beanClass != null ) { 193 String name = elementDescriptor.getPropertyName(); 194 PropertyDescriptor descriptor = 195 getPropertyDescriptor( beanClass, name ); 196 197 if ( descriptor != null ) { 198 configureProperty( 199 elementDescriptor, 200 descriptor, 201 updateMethodName, 202 beanClass ); 203 204 getProcessedPropertyNameSet().add( name ); 205 } 206 } 207 } 208 209 210 221 private void configureProperty( 222 ElementDescriptor elementDescriptor, 223 PropertyDescriptor propertyDescriptor, 224 String updateMethodName, 225 Class beanClass ) { 226 227 Class type = propertyDescriptor.getPropertyType(); 228 Method readMethod = propertyDescriptor.getReadMethod(); 229 Method writeMethod = propertyDescriptor.getWriteMethod(); 230 231 String existingLocalName = elementDescriptor.getLocalName(); 232 if (existingLocalName == null || "".equals(existingLocalName)) { 233 elementDescriptor.setLocalName( propertyDescriptor.getName() ); 234 } 235 elementDescriptor.setPropertyType( type ); 236 237 241 if ( readMethod == null ) { 242 log.trace( "No read method" ); 243 return; 244 } 245 246 if ( log.isTraceEnabled() ) { 247 log.trace( "Read method=" + readMethod.getName() ); 248 } 249 250 252 if ( Class .class.equals( type ) && "class".equals( propertyDescriptor.getName() ) ) { 254 log.trace( "Ignoring class property" ); 255 return; 256 } 257 if ( getXMLIntrospector().isPrimitiveType( type ) ) { 258 elementDescriptor.setTextExpression( new MethodExpression( readMethod ) ); 259 260 } else if ( getXMLIntrospector().isLoopType( type ) ) { 261 log.trace("Loop type ??"); 262 263 elementDescriptor.setContextExpression( 266 new IteratorExpression( new MethodExpression( readMethod ) ) 267 ); 268 elementDescriptor.setHollow(true); 269 270 writeMethod = null; 271 272 if (Map .class.isAssignableFrom(type)) { 273 elementDescriptor.setLocalName( "entry" ); 274 ElementDescriptor keyDescriptor = new ElementDescriptor( "key" ); 276 keyDescriptor.setHollow( true ); 277 elementDescriptor.addElementDescriptor( keyDescriptor ); 278 279 ElementDescriptor valueDescriptor = new ElementDescriptor( "value" ); 280 valueDescriptor.setHollow( true ); 281 elementDescriptor.addElementDescriptor( valueDescriptor ); 282 } 283 284 } else { 285 log.trace( "Standard property" ); 286 elementDescriptor.setHollow(true); 287 elementDescriptor.setContextExpression( new MethodExpression( readMethod ) ); 288 } 289 290 if (updateMethodName == null) { 292 if ( writeMethod != null ) { 294 elementDescriptor.setUpdater( new MethodUpdater( writeMethod ) ); 295 } 296 297 } else { 298 if ( log.isTraceEnabled() ) { 300 log.trace( "Finding custom method: " ); 301 log.trace( " on:" + beanClass ); 302 log.trace( " name:" + updateMethodName ); 303 } 304 305 Method updateMethod = null; 306 Method [] methods = beanClass.getMethods(); 307 for ( int i = 0, size = methods.length; i < size; i++ ) { 308 Method method = methods[i]; 309 if ( updateMethodName.equals( method.getName() ) ) { 310 if (methods[i].getParameterTypes().length == 1) { 313 updateMethod = methods[i]; 315 if ( log.isTraceEnabled() ) { 316 log.trace("Matched method:" + updateMethod); 317 } 318 break; 320 } 321 } 322 } 323 324 if (updateMethod == null) { 325 if ( log.isInfoEnabled() ) { 326 327 log.info("No method with name '" + updateMethodName + "' found for update"); 328 } 329 } else { 330 331 elementDescriptor.setUpdater( new MethodUpdater( updateMethod ) ); 332 elementDescriptor.setSingularPropertyType( updateMethod.getParameterTypes()[0] ); 333 if ( log.isTraceEnabled() ) { 334 log.trace( "Set custom updater on " + elementDescriptor); 335 } 336 } 337 } 338 } 339 } 340 | Popular Tags |