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 if (!getXMLIntrospector().getConfiguration().getPropertySuppressionStrategy()
113 .suppressProperty(
114 beanClass,
115 descriptor.getPropertyType(),
116 descriptor.getName())) {
117 Descriptor nodeDescriptor =
118 getXMLIntrospector().createXMLDescriptor(new BeanProperty(descriptor));
119 if ( nodeDescriptor != null ) {
120 addDescriptor( nodeDescriptor );
121 }
122 }
123 }
124 }
125 } catch (Exception e) {
126 log.info( "Caught introspection exception", e );
127 }
128 }
129 }
130
131
132
133
134
135 /***
136 * Add a desciptor to the top object on the Digester stack.
137 *
138 * @param nodeDescriptor add this <code>NodeDescriptor</code>. Must not be null.
139 * @throws SAXException if the parent for the addDefaults element is not a <element>
140 * or if the top object on the stack is not a <code>XMLBeanInfo</code> or a
141 * <code>ElementDescriptor</code>
142 * @deprecated 0.5 replaced {@link #addDescriptor( Descriptor )}
143 */
144 protected void addDescriptor( NodeDescriptor nodeDescriptor ) throws SAXException {
145 addDescriptor( (Descriptor) nodeDescriptor );
146 }
147
148 /***
149 * Add a desciptor to the top object on the Digester stack.
150 *
151 * @param nodeDescriptor add this <code>NodeDescriptor</code>. Must not be null.
152 * @throws SAXException if the parent for the addDefaults element is not a <element>
153 * or if the top object on the stack is not a <code>XMLBeanInfo</code> or a
154 * <code>ElementDescriptor</code>
155 * @since 0.5
156 */
157 protected void addDescriptor( Descriptor nodeDescriptor ) throws SAXException {
158 Object top = digester.peek();
159 if ( top instanceof XMLBeanInfo ) {
160 log.warn( "It is advisable to put an <addDefaults/> element inside an <element> tag" );
161
162 XMLBeanInfo beanInfo = (XMLBeanInfo) top;
163
164
165 if ( nodeDescriptor instanceof ElementDescriptor ) {
166 ElementDescriptor elementDescriptor = (ElementDescriptor) nodeDescriptor;
167 ElementDescriptor root = beanInfo.getElementDescriptor() ;
168 if ( root == null ) {
169 beanInfo.setElementDescriptor( elementDescriptor );
170 } else {
171 root.addElementDescriptor( elementDescriptor );
172 }
173 } else {
174 throw new SAXException(
175 "the <addDefaults> element should be within an <element> tag" );
176 }
177 } else if ( top instanceof ElementDescriptor ) {
178 ElementDescriptor parent = (ElementDescriptor) top;
179 if ( nodeDescriptor instanceof ElementDescriptor ) {
180 parent.addElementDescriptor( (ElementDescriptor) nodeDescriptor );
181 } else {
182 parent.addAttributeDescriptor( (AttributeDescriptor) nodeDescriptor );
183 }
184 } else {
185 throw new SAXException(
186 "Invalid use of <addDefaults>. It should be nested inside <element> element" );
187 }
188 }
189
190 /***
191 * Gets an <code>ElementDescriptor</code> for the top on digester's stack.
192 *
193 * @return the top object or the element description if the top object
194 * is an <code>ElementDescriptor</code> or a <code>XMLBeanInfo</code> class (respectively)
195 * Otherwise null.
196 */
197 protected ElementDescriptor getRootElementDescriptor() {
198 Object top = digester.peek();
199 if ( top instanceof XMLBeanInfo ) {
200 XMLBeanInfo beanInfo = (XMLBeanInfo) top;
201 return beanInfo.getElementDescriptor();
202
203 } else if ( top instanceof ElementDescriptor ) {
204 ElementDescriptor parent = (ElementDescriptor) top;
205
206 return parent;
207 }
208 return null;
209 }
210 }