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