View Javadoc

1   package org.apache.commons.betwixt.digester;
2   /*
3    * Copyright 2001-2004 The Apache Software Foundation.
4    * 
5    * Licensed under the Apache License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */ 
17  import java.beans.PropertyDescriptor;
18  
19  import org.apache.commons.betwixt.ElementDescriptor;
20  import org.apache.commons.betwixt.XMLBeanInfo;
21  import org.apache.commons.betwixt.XMLUtils;
22  import org.apache.commons.betwixt.expression.ConstantExpression;
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.xml.sax.Attributes;
26  import org.xml.sax.SAXException;
27  
28  /*** 
29    * <p><code>ElementRule</code> the digester Rule for parsing 
30    * the &lt;element&gt; elements.</p>
31    *
32    * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
33    * @version $Id: ElementRule.java,v 1.14.2.1 2004/06/19 16:24:10 rdonkin Exp $
34    */
35  public class ElementRule extends MappedPropertyRule {
36  
37      /*** Logger */
38      private static Log log = LogFactory.getLog( ElementRule.class );
39      /*** 
40       * Sets the log for this class 
41       * 
42       * @param newLog the new Log implementation for this class to use
43       * @since 0.5
44       */
45      public static final void setLog(Log newLog) {
46          log = newLog;
47      }
48  
49      /*** Class for which the .bewixt file is being digested */
50      private Class beanClass;
51      /*** Base constructor */
52      public ElementRule() {}
53      
54      // Rule interface
55      //-------------------------------------------------------------------------    
56      
57      /***
58       * Process the beginning of this element.
59       *
60       * @param attributes The attribute list of this element
61       * @throws SAXException 1. If this tag's parent is not either an info or element tag.
62       * 2. If the name attribute is not valid XML element name.
63       * 3. If the name attribute is not present 
64       * 4. If the class attribute is not a loadable (fully qualified) class name
65       */
66      public void begin(Attributes attributes) throws SAXException {
67          String name = attributes.getValue( "name" );
68          
69          // check that the name attribute is present 
70          if ( name == null || name.trim().equals( "" ) ) {
71              throw new SAXException("Name attribute is required.");
72          }
73          
74          // check that name is well formed 
75          if ( !XMLUtils.isWellFormedXMLName( name ) ) {
76              throw new SAXException("'" + name + "' would not be a well formed xml element name.");
77          }
78          
79          ElementDescriptor descriptor = new ElementDescriptor();
80          descriptor.setQualifiedName( name );
81          descriptor.setLocalName( name );
82          String uri = attributes.getValue( "uri" );
83          if ( uri != null ) {
84              descriptor.setURI( uri );        
85          }
86          
87          String propertyName = attributes.getValue( "property" );
88          descriptor.setPropertyName( propertyName );
89          
90          String propertyType = attributes.getValue( "type" );
91          
92          if (log.isTraceEnabled()) {
93              log.trace(
94                      "(BEGIN) name=" + name + " uri=" + uri 
95                      + " property=" + propertyName + " type=" + propertyType);
96          }
97          
98          // set the property type using reflection
99          descriptor.setPropertyType( 
100             getPropertyType( propertyType, beanClass, propertyName ) 
101         );
102         
103         String implementationClass = attributes.getValue( "class" );
104         if ( log.isTraceEnabled() ) {
105             log.trace("'class' attribute=" + implementationClass);
106         }
107         if ( implementationClass != null ) {
108             try {
109                 
110                 Class clazz = Class.forName(implementationClass);
111                 descriptor.setImplementationClass( clazz );
112                 
113             } catch (Exception e)  {
114                 if ( log.isDebugEnabled() ) {
115                     log.debug("Cannot load class named: " + implementationClass, e);
116                 }
117                 throw new SAXException("Cannot load class named: " + implementationClass);
118             }
119         }
120         
121         if ( propertyName != null && propertyName.length() > 0 ) {
122             configureDescriptor(descriptor, attributes.getValue( "updater" ));
123             
124         } else {
125             String value = attributes.getValue( "value" );
126             if ( value != null ) {
127                 descriptor.setTextExpression( new ConstantExpression( value ) );
128             }
129         }
130         
131         Object top = digester.peek();
132         if ( top instanceof XMLBeanInfo ) {
133             XMLBeanInfo beanInfo = (XMLBeanInfo) top;
134             beanInfo.setElementDescriptor( descriptor );
135             beanClass = beanInfo.getBeanClass();
136             
137         } else if ( top instanceof ElementDescriptor ) {
138             ElementDescriptor parent = (ElementDescriptor) top;
139             parent.addElementDescriptor( descriptor );
140             
141         } else {
142             throw new SAXException( "Invalid use of <element>. It should " 
143                 + "be nested inside <info> or other <element> nodes" );
144         }
145 
146         digester.push(descriptor);        
147     }
148 
149 
150     /***
151      * Process the end of this element.
152      */
153     public void end() {
154         Object top = digester.pop();
155     }
156 
157     
158     // Implementation methods
159     //-------------------------------------------------------------------------    
160     
161     /*** 
162      * Sets the Expression and Updater from a bean property name 
163      * Uses the default updater (from the standard java bean property).
164      *
165      * @param elementDescriptor configure this <code>ElementDescriptor</code>
166      * since 0.5
167      */
168     protected void configureDescriptor(ElementDescriptor elementDescriptor) {
169         configureDescriptor( elementDescriptor, null );
170     }       
171     
172     /*** 
173      * Sets the Expression and Updater from a bean property name 
174      * Allows a custom updater to be passed in.
175      *
176      * @param elementDescriptor configure this <code>ElementDescriptor</code>
177      * @param updateMethodName custom update method. If null, then use standard
178      * since 0.5
179      */
180     protected void configureDescriptor(
181                                         ElementDescriptor elementDescriptor,
182                                         String updateMethodName) {
183         Class beanClass = getBeanClass();
184         if ( beanClass != null ) {
185             String name = elementDescriptor.getPropertyName();
186             PropertyDescriptor descriptor = 
187                 getPropertyDescriptor( beanClass, name );
188             
189             if ( descriptor != null ) { 
190                 XMLIntrospectorHelper
191                     .configureProperty( 
192                                         elementDescriptor, 
193                                         descriptor, 
194                                         updateMethodName, 
195                                         beanClass );
196                 
197                 getProcessedPropertyNameSet().add( name );
198             }
199         }
200     }  
201 }