1 package org.apache.commons.betwixt.digester;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 <element> 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
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
70 if ( name == null || name.trim().equals( "" ) ) {
71 throw new SAXException("Name attribute is required.");
72 }
73
74
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
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
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 }