1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.betwixt.digester;
17
18 import java.beans.BeanInfo;
19 import java.beans.Introspector;
20 import java.beans.PropertyDescriptor;
21 import java.util.Set;
22
23 import org.apache.commons.betwixt.AttributeDescriptor;
24 import org.apache.commons.betwixt.BeanProperty;
25 import org.apache.commons.betwixt.Descriptor;
26 import org.apache.commons.betwixt.ElementDescriptor;
27 import org.apache.commons.betwixt.NodeDescriptor;
28 import org.apache.commons.betwixt.XMLBeanInfo;
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31 import org.xml.sax.Attributes;
32 import org.xml.sax.SAXException;
33
34 /*** <p><code>AddDefaultsRule</code> appends all the default properties
35 * to the current element.</p>
36 *
37 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
38 */
39 public class AddDefaultsRule extends RuleSupport {
40
41 /*** Logger */
42 private static final Log log = LogFactory.getLog( AddDefaultsRule.class );
43
44 /*** Base constructor */
45 public AddDefaultsRule() {
46 }
47
48
49
50
51 /***
52 * Process the beginning of this element.
53 *
54 * @param attributes The attribute list of this element
55 * @throws Exception generally this will indicate an unrecoverable error
56 */
57 public void begin(String name, String namespace, Attributes attributes) throws Exception {
58 boolean addProperties = true;
59 String addPropertiesAttributeValue = attributes.getValue("add-properties");
60 if (addPropertiesAttributeValue != null)
61 {
62 addProperties = Boolean.valueOf(addPropertiesAttributeValue).booleanValue();
63 }
64
65 boolean addAdders = true;
66 String addAddersAttributeValue = attributes.getValue("add-adders");
67 if (addAddersAttributeValue != null)
68 {
69 addProperties = Boolean.valueOf(addAddersAttributeValue).booleanValue();
70 }
71
72 if (addProperties) {
73 addDefaultProperties();
74 }
75
76 if (addAdders) {
77 addAdders();
78 }
79 }
80
81 /***
82 * Adds default adder methods
83 */
84 private void addAdders() {
85 Class beanClass = getBeanClass();
86
87 getXMLIntrospector().defaultAddMethods(
88 getRootElementDescriptor(),
89 beanClass );
90 }
91
92 /***
93 * Adds default property methods
94 *
95 */
96 private void addDefaultProperties() {
97 Class beanClass = getBeanClass();
98 Set processedProperties = getProcessedPropertyNameSet();
99 if ( beanClass != null ) {
100 try {
101 boolean attributesForPrimitives = getXMLInfoDigester().isAttributesForPrimitives();
102 BeanInfo beanInfo = Introspector.getBeanInfo( beanClass );
103 PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
104 if ( descriptors != null ) {
105 for ( int i = 0, size = descriptors.length; i < size; i++ ) {
106 PropertyDescriptor descriptor = descriptors[i];
107
108 String propertyName = descriptor.getName();
109 if ( processedProperties.contains( propertyName ) ) {
110 continue;
111 }
112 Descriptor nodeDescriptor =
113 getXMLIntrospector().createXMLDescriptor(new BeanProperty(descriptor));
114 if ( nodeDescriptor != null ) {
115 addDescriptor( nodeDescriptor );
116 }
117 }
118 }
119 } catch (Exception e) {
120 log.info( "Caught introspection exception", e );
121 }
122 }
123 }
124
125
126
127
128
129 /***
130 * Add a desciptor to the top object on the Digester stack.
131 *
132 * @param nodeDescriptor add this <code>NodeDescriptor</code>. Must not be null.
133 * @throws SAXException if the parent for the addDefaults element is not a <element>
134 * or if the top object on the stack is not a <code>XMLBeanInfo</code> or a
135 * <code>ElementDescriptor</code>
136 * @deprecated 0.5 replaced {@link #addDescriptor( Descriptor )}
137 */
138 protected void addDescriptor( NodeDescriptor nodeDescriptor ) throws SAXException {
139 addDescriptor( (Descriptor) nodeDescriptor );
140 }
141
142 /***
143 * Add a desciptor to the top object on the Digester stack.
144 *
145 * @param nodeDescriptor add this <code>NodeDescriptor</code>. Must not be null.
146 * @throws SAXException if the parent for the addDefaults element is not a <element>
147 * or if the top object on the stack is not a <code>XMLBeanInfo</code> or a
148 * <code>ElementDescriptor</code>
149 * @since 0.5
150 */
151 protected void addDescriptor( Descriptor nodeDescriptor ) throws SAXException {
152 Object top = digester.peek();
153 if ( top instanceof XMLBeanInfo ) {
154 log.warn( "It is advisable to put an <addDefaults/> element inside an <element> tag" );
155
156 XMLBeanInfo beanInfo = (XMLBeanInfo) top;
157
158
159 if ( nodeDescriptor instanceof ElementDescriptor ) {
160 ElementDescriptor elementDescriptor = (ElementDescriptor) nodeDescriptor;
161 ElementDescriptor root = beanInfo.getElementDescriptor() ;
162 if ( root == null ) {
163 beanInfo.setElementDescriptor( elementDescriptor );
164 } else {
165 root.addElementDescriptor( elementDescriptor );
166 }
167 } else {
168 throw new SAXException(
169 "the <addDefaults> element should be within an <element> tag" );
170 }
171 } else if ( top instanceof ElementDescriptor ) {
172 ElementDescriptor parent = (ElementDescriptor) top;
173 if ( nodeDescriptor instanceof ElementDescriptor ) {
174 parent.addElementDescriptor( (ElementDescriptor) nodeDescriptor );
175 } else {
176 parent.addAttributeDescriptor( (AttributeDescriptor) nodeDescriptor );
177 }
178 } else {
179 throw new SAXException(
180 "Invalid use of <addDefaults>. It should be nested inside <element> element" );
181 }
182 }
183
184 /***
185 * Gets an <code>ElementDescriptor</code> for the top on digester's stack.
186 *
187 * @return the top object or the element description if the top object
188 * is an <code>ElementDescriptor</code> or a <code>XMLBeanInfo</code> class (respectively)
189 * Otherwise null.
190 */
191 protected ElementDescriptor getRootElementDescriptor() {
192 Object top = digester.peek();
193 if ( top instanceof XMLBeanInfo ) {
194 XMLBeanInfo beanInfo = (XMLBeanInfo) top;
195 return beanInfo.getElementDescriptor();
196
197 } else if ( top instanceof ElementDescriptor ) {
198 ElementDescriptor parent = (ElementDescriptor) top;
199
200 return parent;
201 }
202 return null;
203 }
204 }