KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > betwixt > digester > XMLIntrospectorHelper


1 package org.apache.commons.betwixt.digester;
2
3 /*
4  * Copyright 2001-2004 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 import java.beans.IntrospectionException JavaDoc;
20 import java.beans.Introspector JavaDoc;
21 import java.beans.PropertyDescriptor JavaDoc;
22 import java.lang.reflect.Method JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.Date JavaDoc;
25 import java.util.Enumeration JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.Map JavaDoc;
29
30 import org.apache.commons.betwixt.AttributeDescriptor;
31 import org.apache.commons.betwixt.ElementDescriptor;
32 import org.apache.commons.betwixt.NodeDescriptor;
33 import org.apache.commons.betwixt.XMLIntrospector;
34 import org.apache.commons.betwixt.expression.IteratorExpression;
35 import org.apache.commons.betwixt.expression.MapEntryAdder;
36 import org.apache.commons.betwixt.expression.MethodExpression;
37 import org.apache.commons.betwixt.expression.MethodUpdater;
38 import org.apache.commons.betwixt.strategy.PluralStemmer;
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41
42 /**
43   * <p><code>XMLIntrospectorHelper</code> a helper class for
44   * common code shared between the digestor and introspector.</p>
45   *
46   * TODO this class will be deprecated soon
47   * need to move the isLoop and isPrimitiveType but probably need to
48   * think about whether they need replacing with something different.
49   * @author <a HREF="mailto:jstrachan@apache.org">James Strachan</a>
50   * @author <a HREF="mailto:martin@mvdb.net">Martin van den Bemt</a>
51   */

52 public class XMLIntrospectorHelper {
53
54     /** Log used for logging (Doh!) */
55     protected static Log log = LogFactory.getLog( XMLIntrospectorHelper.class );
56     
57     /** Base constructor */
58     public XMLIntrospectorHelper() {
59     }
60     
61     /**
62      * <p>Gets the current logging implementation.</p>
63      *
64      * @return current log
65      */

66     public static Log getLog() {
67         return log;
68     }
69
70     /**
71      * <p>Sets the current logging implementation.</p>
72      *
73      * @param aLog use this <code>Log</code>
74      */

75     public static void setLog(Log aLog) {
76         log = aLog;
77     }
78     
79
80
81     /**
82      * Process a property.
83      * Go through and work out whether it's a loop property, a primitive or a standard.
84      * The class property is ignored.
85      *
86      * @param propertyDescriptor create a <code>NodeDescriptor</code> for this property
87      * @param useAttributesForPrimitives write primitives as attributes (rather than elements)
88      * @param introspector use this <code>XMLIntrospector</code>
89      * @return a correctly configured <code>NodeDescriptor</code> for the property
90      * @throws IntrospectionException when bean introspection fails
91      * @deprecated 0.5 this method has been replaced by {@link XMLIntrospector#createDescriptor}
92      */

93     public static NodeDescriptor createDescriptor(
94         PropertyDescriptor JavaDoc propertyDescriptor,
95         boolean useAttributesForPrimitives,
96         XMLIntrospector introspector
97     ) throws IntrospectionException JavaDoc {
98         String JavaDoc name = propertyDescriptor.getName();
99         Class JavaDoc type = propertyDescriptor.getPropertyType();
100        
101         if (log.isTraceEnabled()) {
102             log.trace("Creating descriptor for property: name="
103                 + name + " type=" + type);
104         }
105         
106         NodeDescriptor nodeDescriptor = null;
107         Method JavaDoc readMethod = propertyDescriptor.getReadMethod();
108         Method JavaDoc writeMethod = propertyDescriptor.getWriteMethod();
109         
110         if ( readMethod == null ) {
111             if (log.isTraceEnabled()) {
112                 log.trace( "No read method for property: name="
113                     + name + " type=" + type);
114             }
115             return null;
116         }
117         
118         if ( log.isTraceEnabled() ) {
119             log.trace( "Read method=" + readMethod.getName() );
120         }
121         
122         // choose response from property type
123

124         // XXX: ignore class property ??
125
if ( Class JavaDoc.class.equals( type ) && "class".equals( name ) ) {
126             log.trace( "Ignoring class property" );
127             return null;
128         }
129         if ( isPrimitiveType( type ) ) {
130             if (log.isTraceEnabled()) {
131                 log.trace( "Primitive type: " + name);
132             }
133             if ( useAttributesForPrimitives ) {
134                 if (log.isTraceEnabled()) {
135                     log.trace( "Adding property as attribute: " + name );
136                 }
137                 nodeDescriptor = new AttributeDescriptor();
138             } else {
139                 if (log.isTraceEnabled()) {
140                     log.trace( "Adding property as element: " + name );
141                 }
142                 nodeDescriptor = new ElementDescriptor(true);
143             }
144             nodeDescriptor.setTextExpression( new MethodExpression( readMethod ) );
145             
146             if ( writeMethod != null ) {
147                 nodeDescriptor.setUpdater( new MethodUpdater( writeMethod ) );
148             }
149         } else if ( isLoopType( type ) ) {
150             if (log.isTraceEnabled()) {
151                 log.trace("Loop type: " + name);
152                 log.trace("Wrap in collections? " + introspector.isWrapCollectionsInElement());
153             }
154             ElementDescriptor loopDescriptor = new ElementDescriptor();
155             loopDescriptor.setContextExpression(
156                 new IteratorExpression( new MethodExpression( readMethod ) )
157             );
158             loopDescriptor.setWrapCollectionsInElement(
159                         introspector.isWrapCollectionsInElement());
160             // XXX: need to support some kind of 'add' or handle arrays, Lists or indexed properties
161
//loopDescriptor.setUpdater( new MethodUpdater( writeMethod ) );
162
if ( Map JavaDoc.class.isAssignableFrom( type ) ) {
163                 loopDescriptor.setQualifiedName( "entry" );
164                 // add elements for reading
165
loopDescriptor.addElementDescriptor( new ElementDescriptor( "key" ) );
166                 loopDescriptor.addElementDescriptor( new ElementDescriptor( "value" ) );
167             }
168
169             ElementDescriptor elementDescriptor = new ElementDescriptor();
170             elementDescriptor.setWrapCollectionsInElement(
171                         introspector.isWrapCollectionsInElement());
172             elementDescriptor.setElementDescriptors( new ElementDescriptor[] { loopDescriptor } );
173             
174             nodeDescriptor = elementDescriptor;
175         } else {
176             if (log.isTraceEnabled()) {
177                 log.trace( "Standard property: " + name);
178             }
179             ElementDescriptor elementDescriptor = new ElementDescriptor();
180             elementDescriptor.setContextExpression( new MethodExpression( readMethod ) );
181             if ( writeMethod != null ) {
182                 elementDescriptor.setUpdater( new MethodUpdater( writeMethod ) );
183             }
184             
185             nodeDescriptor = elementDescriptor;
186         }
187
188         if (nodeDescriptor instanceof AttributeDescriptor) {
189             // we want to use the attributemapper only when it is an attribute..
190
nodeDescriptor.setLocalName(
191                 introspector.getAttributeNameMapper().mapTypeToElementName( name ) );
192         } else {
193             nodeDescriptor.setLocalName(
194                 introspector.getElementNameMapper().mapTypeToElementName( name ) );
195         }
196   
197         nodeDescriptor.setPropertyName( propertyDescriptor.getName() );
198         nodeDescriptor.setPropertyType( type );
199         
200         // XXX: associate more bean information with the descriptor?
201
//nodeDescriptor.setDisplayName( propertyDescriptor.getDisplayName() );
202
//nodeDescriptor.setShortDescription( propertyDescriptor.getShortDescription() );
203

204         if (log.isTraceEnabled()) {
205             log.trace("Created descriptor:");
206             log.trace(nodeDescriptor);
207         }
208         return nodeDescriptor;
209     }
210     
211     /**
212      * Configure an <code>ElementDescriptor</code> from a <code>PropertyDescriptor</code>.
213      * This uses default element updater (the write method of the property).
214      *
215      * @param elementDescriptor configure this <code>ElementDescriptor</code>
216      * @param propertyDescriptor configure from this <code>PropertyDescriptor</code>
217      * @deprecated 0.6 unused
218      */

219     public static void configureProperty(
220                                     ElementDescriptor elementDescriptor,
221                                     PropertyDescriptor JavaDoc propertyDescriptor ) {
222                                     
223         configureProperty( elementDescriptor, propertyDescriptor, null, null);
224     }
225                                     
226     /**
227      * Configure an <code>ElementDescriptor</code> from a <code>PropertyDescriptor</code>.
228      * A custom update method may be set.
229      *
230      * @param elementDescriptor configure this <code>ElementDescriptor</code>
231      * @param propertyDescriptor configure from this <code>PropertyDescriptor</code>
232      * @param updateMethodName the name of the custom updater method to user.
233      * If null, then then
234      * @param beanClass the <code>Class</code> from which the update method should be found.
235      * This may be null only when <code>updateMethodName</code> is also null.
236      * @since 0.5
237      * @deprecated 0.6 moved into ElementRule
238      */

239     public static void configureProperty(
240                                     ElementDescriptor elementDescriptor,
241                                     PropertyDescriptor JavaDoc propertyDescriptor,
242                                     String JavaDoc updateMethodName,
243                                     Class JavaDoc beanClass ) {
244         
245         Class JavaDoc type = propertyDescriptor.getPropertyType();
246         Method JavaDoc readMethod = propertyDescriptor.getReadMethod();
247         Method JavaDoc writeMethod = propertyDescriptor.getWriteMethod();
248         
249         elementDescriptor.setLocalName( propertyDescriptor.getName() );
250         elementDescriptor.setPropertyType( type );
251         
252         // XXX: associate more bean information with the descriptor?
253
//nodeDescriptor.setDisplayName( propertyDescriptor.getDisplayName() );
254
//nodeDescriptor.setShortDescription( propertyDescriptor.getShortDescription() );
255

256         if ( readMethod == null ) {
257             log.trace( "No read method" );
258             return;
259         }
260         
261         if ( log.isTraceEnabled() ) {
262             log.trace( "Read method=" + readMethod.getName() );
263         }
264         
265         // choose response from property type
266

267         // XXX: ignore class property ??
268
if ( Class JavaDoc.class.equals( type ) && "class".equals( propertyDescriptor.getName() ) ) {
269             log.trace( "Ignoring class property" );
270             return;
271         }
272         if ( isPrimitiveType( type ) ) {
273             elementDescriptor.setTextExpression( new MethodExpression( readMethod ) );
274             
275         } else if ( isLoopType( type ) ) {
276             log.trace("Loop type ??");
277             
278             // don't wrap this in an extra element as its specified in the
279
// XML descriptor so no need.
280
elementDescriptor.setContextExpression(
281                 new IteratorExpression( new MethodExpression( readMethod ) )
282             );
283
284             writeMethod = null;
285         } else {
286             log.trace( "Standard property" );
287             elementDescriptor.setContextExpression( new MethodExpression( readMethod ) );
288         }
289     
290         // see if we have a custom method update name
291
if (updateMethodName == null) {
292             // set standard write method
293
if ( writeMethod != null ) {
294                 elementDescriptor.setUpdater( new MethodUpdater( writeMethod ) );
295             }
296             
297         } else {
298             // see if we can find and set the custom method
299
if ( log.isTraceEnabled() ) {
300                 log.trace( "Finding custom method: " );
301                 log.trace( " on:" + beanClass );
302                 log.trace( " name:" + updateMethodName );
303             }
304             
305             Method JavaDoc updateMethod = null;
306             Method JavaDoc[] methods = beanClass.getMethods();
307             for ( int i = 0, size = methods.length; i < size; i++ ) {
308                 Method JavaDoc method = methods[i];
309                 if ( updateMethodName.equals( method.getName() ) ) {
310                     // we have a matching name
311
// check paramters are correct
312
if (methods[i].getParameterTypes().length == 1) {
313                         // we'll use first match
314
updateMethod = methods[i];
315                         if ( log.isTraceEnabled() ) {
316                             log.trace("Matched method:" + updateMethod);
317                         }
318                         // done since we're using the first match
319
break;
320                     }
321                 }
322             }
323             
324             if (updateMethod == null) {
325                 if ( log.isInfoEnabled() ) {
326                     
327                     log.info("No method with name '" + updateMethodName + "' found for update");
328                 }
329             } else {
330     
331                 elementDescriptor.setUpdater( new MethodUpdater( updateMethod ) );
332                 elementDescriptor.setSingularPropertyType( updateMethod.getParameterTypes()[0] );
333                 if ( log.isTraceEnabled() ) {
334                     log.trace( "Set custom updater on " + elementDescriptor);
335                 }
336             }
337         }
338     }
339     
340     /**
341      * Configure an <code>AttributeDescriptor</code> from a <code>PropertyDescriptor</code>
342      *
343      * @param attributeDescriptor configure this <code>AttributeDescriptor</code>
344      * @param propertyDescriptor configure from this <code>PropertyDescriptor</code>
345      * @deprecated 0.6 moved into AttributeRule
346      */

347     public static void configureProperty(
348                                     AttributeDescriptor attributeDescriptor,
349                                     PropertyDescriptor JavaDoc propertyDescriptor ) {
350         Class JavaDoc type = propertyDescriptor.getPropertyType();
351         Method JavaDoc readMethod = propertyDescriptor.getReadMethod();
352         Method JavaDoc writeMethod = propertyDescriptor.getWriteMethod();
353         
354         if ( readMethod == null ) {
355             log.trace( "No read method" );
356             return;
357         }
358         
359         if ( log.isTraceEnabled() ) {
360             log.trace( "Read method=" + readMethod );
361         }
362         
363         // choose response from property type
364

365         // XXX: ignore class property ??
366
if ( Class JavaDoc.class.equals( type ) && "class".equals( propertyDescriptor.getName() ) ) {
367             log.trace( "Ignoring class property" );
368             return;
369         }
370         if ( isLoopType( type ) ) {
371             log.warn( "Using loop type for an attribute. Type = "
372                     + type.getName() + " attribute: " + attributeDescriptor.getQualifiedName() );
373         }
374
375         log.trace( "Standard property" );
376         attributeDescriptor.setTextExpression( new MethodExpression( readMethod ) );
377         
378         if ( writeMethod != null ) {
379             attributeDescriptor.setUpdater( new MethodUpdater( writeMethod ) );
380         }
381         
382         attributeDescriptor.setLocalName( propertyDescriptor.getName() );
383         attributeDescriptor.setPropertyType( type );
384         
385         // XXX: associate more bean information with the descriptor?
386
//nodeDescriptor.setDisplayName( propertyDescriptor.getDisplayName() );
387
//nodeDescriptor.setShortDescription( propertyDescriptor.getShortDescription() );
388
}
389     
390
391     /**
392      * Add any addPropety(PropertyType) methods as Updaters
393      * which are often used for 1-N relationships in beans.
394      * <br>
395      * The tricky part here is finding which ElementDescriptor corresponds
396      * to the method. e.g. a property 'items' might have an Element descriptor
397      * which the method addItem() should match to.
398      * <br>
399      * So the algorithm we'll use
400      * by default is to take the decapitalized name of the property being added
401      * and find the first ElementDescriptor that matches the property starting with
402      * the string. This should work for most use cases.
403      * e.g. addChild() would match the children property.
404      *
405      * @param introspector use this <code>XMLIntrospector</code> for introspection
406      * @param rootDescriptor add defaults to this descriptor
407      * @param beanClass the <code>Class</code> to which descriptor corresponds
408      * @deprecated 0.6 use the method in XMLIntrospector instead
409      */

410     public static void defaultAddMethods(
411                                             XMLIntrospector introspector,
412                                             ElementDescriptor rootDescriptor,
413                                             Class JavaDoc beanClass ) {
414         // lets iterate over all methods looking for one of the form
415
// add*(PropertyType)
416
if ( beanClass != null ) {
417             Method JavaDoc[] methods = beanClass.getMethods();
418             for ( int i = 0, size = methods.length; i < size; i++ ) {
419                 Method JavaDoc method = methods[i];
420                 String JavaDoc name = method.getName();
421                 if ( name.startsWith( "add" ) ) {
422                     // XXX: should we filter out non-void returning methods?
423
// some beans will return something as a helper
424
Class JavaDoc[] types = method.getParameterTypes();
425                     if ( types != null) {
426                         if ( log.isTraceEnabled() ) {
427                             log.trace("Searching for match for " + method);
428                         }
429                         
430                         if ( ( types.length == 1 ) || types.length == 2 ) {
431                             String JavaDoc propertyName = Introspector.decapitalize( name.substring(3) );
432                             if (propertyName.length() == 0)
433                                 continue;
434                             if ( log.isTraceEnabled() ) {
435                                 log.trace( name + "->" + propertyName );
436                             }
437     
438                             // now lets try find the ElementDescriptor which displays
439
// a property which starts with propertyName
440
// and if so, we'll set a new Updater on it if there
441
// is not one already
442
ElementDescriptor descriptor =
443                                 findGetCollectionDescriptor(
444                                                             introspector,
445                                                             rootDescriptor,
446                                                             propertyName );
447     
448                             if ( log.isDebugEnabled() ) {
449                                 log.debug( "!! " + propertyName + " -> " + descriptor );
450                                 log.debug( "!! " + name + " -> "
451                                 + (descriptor!=null?descriptor.getPropertyName():"") );
452                             }
453                             if ( descriptor != null ) {
454                                 boolean isMapDescriptor
455                                     = Map JavaDoc.class.isAssignableFrom( descriptor.getPropertyType() );
456                                 if ( !isMapDescriptor && types.length == 1 ) {
457                                     // this may match a standard collection or iteration
458
log.trace("Matching collection or iteration");
459                                     
460                                     descriptor.setUpdater( new MethodUpdater( method ) );
461                                     descriptor.setSingularPropertyType( types[0] );
462                                     
463                                     if ( log.isDebugEnabled() ) {
464                                         log.debug( "!! " + method);
465                                         log.debug( "!! " + types[0]);
466                                     }
467                                     
468                                     // is there a child element with no localName
469
ElementDescriptor[] children
470                                         = descriptor.getElementDescriptors();
471                                     if ( children != null && children.length > 0 ) {
472                                         ElementDescriptor child = children[0];
473                                         String JavaDoc localName = child.getLocalName();
474                                         if ( localName == null || localName.length() == 0 ) {
475                                             child.setLocalName(
476                                                 introspector.getElementNameMapper()
477                                                     .mapTypeToElementName( propertyName ) );
478                                         }
479                                     }
480
481                                 } else if ( isMapDescriptor && types.length == 2 ) {
482                                     // this may match a map
483
log.trace("Matching map");
484                                     ElementDescriptor[] children
485                                         = descriptor.getElementDescriptors();
486                                     // see if the descriptor's been set up properly
487
if ( children.length == 0 ) {
488                                         
489                                         log.info(
490                                             "'entry' descriptor is missing for map. "
491                                             + "Updaters cannot be set");
492                                         
493                                     } else {
494                                         // loop through grandchildren
495
// adding updaters for key and value
496
ElementDescriptor[] grandchildren
497                                             = children[0].getElementDescriptors();
498                                         MapEntryAdder adder = new MapEntryAdder(method);
499                                         for (
500                                             int n=0,
501                                                 noOfGrandChildren = grandchildren.length;
502                                             n < noOfGrandChildren;
503                                             n++ ) {
504                                             if ( "key".equals(
505                                                     grandchildren[n].getLocalName() ) ) {
506                                             
507                                                 grandchildren[n].setUpdater(
508                                                                 adder.getKeyUpdater() );
509                                                 grandchildren[n].setSingularPropertyType(
510                                                                 types[0] );
511                                                 if ( log.isTraceEnabled() ) {
512                                                     log.trace(
513                                                         "Key descriptor: " + grandchildren[n]);
514                                                 }
515                                                 
516                                             } else if (
517                                                 "value".equals(
518                                                     grandchildren[n].getLocalName() ) ) {
519
520                                                 grandchildren[n].setUpdater(
521                                                                     adder.getValueUpdater() );
522                                                 grandchildren[n].setSingularPropertyType(
523                                                                     types[1] );
524                                                 if ( log.isTraceEnabled() ) {
525                                                     log.trace(
526                                                         "Value descriptor: " + grandchildren[n]);
527                                                 }
528                                             }
529                                         }
530                                     }
531                                 }
532                             } else {
533                                 if ( log.isDebugEnabled() ) {
534                                     log.debug(
535                                         "Could not find an ElementDescriptor with property name: "
536                                         + propertyName + " to attach the add method: " + method
537                                     );
538                                 }
539                             }
540                         }
541                     }
542                 }
543             }
544         }
545     }
546     
547     /**
548      * Is this a loop type class?
549      *
550      * @param type is this <code>Class</code> a loop type?
551      * @return true if the type is a loop type, or if type is null
552      */

553     public static boolean isLoopType(Class JavaDoc type) {
554         // check for NPEs
555
if (type == null) {
556             log.trace("isLoopType: type is null");
557             return false;
558         }
559         return type.isArray()
560             || Map JavaDoc.class.isAssignableFrom( type )
561             || Collection JavaDoc.class.isAssignableFrom( type )
562             || Enumeration JavaDoc.class.isAssignableFrom( type )
563             || Iterator JavaDoc.class.isAssignableFrom( type );
564     }
565     
566     
567     /**
568      * Is this a primitive type?
569      *
570      * TODO: this method will probably be removed when primitive types
571      * are subsumed into the simple type concept.
572      * This needs moving into XMLIntrospector so that the list of simple
573      * type can be varied.
574      * @param type is this <code>Class<code> a primitive type?
575      * @return true for primitive types
576      * @deprecated 0.6 replaced by {@link org.apache.commons.betwixt.strategy.TypeBindingStrategy}
577      */

578     public static boolean isPrimitiveType(Class JavaDoc type) {
579         if ( type == null ) {
580             return false;
581             
582         } else if ( type.isPrimitive() ) {
583             return true;
584             
585         } else if ( type.equals( Object JavaDoc.class ) ) {
586             return false;
587         }
588         return type.getName().startsWith( "java.lang." )
589             || Number JavaDoc.class.isAssignableFrom( type )
590             || String JavaDoc.class.isAssignableFrom( type )
591             || Date JavaDoc.class.isAssignableFrom( type )
592             || java.sql.Date JavaDoc.class.isAssignableFrom( type )
593             || java.sql.Time JavaDoc.class.isAssignableFrom( type )
594             || java.sql.Timestamp JavaDoc.class.isAssignableFrom( type )
595             || java.math.BigDecimal JavaDoc.class.isAssignableFrom( type )
596             || java.math.BigInteger JavaDoc.class.isAssignableFrom( type );
597     }
598     
599     // Implementation methods
600
//-------------------------------------------------------------------------
601

602     /**
603      * Attempts to find the element descriptor for the getter property that
604      * typically matches a collection or array. The property name is used
605      * to match. e.g. if an addChild() method is detected the
606      * descriptor for the 'children' getter property should be returned.
607      *
608      * @param introspector use this <code>XMLIntrospector</code>
609      * @param rootDescriptor the <code>ElementDescriptor</code> whose child element will be
610      * searched for a match
611      * @param propertyName the name of the 'adder' method to match
612      * @return <code>ElementDescriptor</code> for the matching getter
613      * @deprecated 0.6 moved into XMLIntrospector
614      */

615     protected static ElementDescriptor findGetCollectionDescriptor(
616                                                 XMLIntrospector introspector,
617                                                 ElementDescriptor rootDescriptor,
618                                                 String JavaDoc propertyName ) {
619         // create the Map of propertyName -> descriptor that the PluralStemmer will choose
620
Map JavaDoc map = new HashMap JavaDoc();
621         //String propertyName = rootDescriptor.getPropertyName();
622
if ( log.isTraceEnabled() ) {
623             log.trace( "findPluralDescriptor( " + propertyName
624                 + " ):root property name=" + rootDescriptor.getPropertyName() );
625         }
626         
627         if (rootDescriptor.getPropertyName() != null) {
628             map.put(propertyName, rootDescriptor);
629         }
630         makeElementDescriptorMap( rootDescriptor, map );
631         
632         PluralStemmer stemmer = introspector.getPluralStemmer();
633         ElementDescriptor elementDescriptor = stemmer.findPluralDescriptor( propertyName, map );
634         
635         if ( log.isTraceEnabled() ) {
636             log.trace(
637                 "findPluralDescriptor( " + propertyName
638                     + " ):ElementDescriptor=" + elementDescriptor );
639         }
640         
641         return elementDescriptor;
642     }
643
644     /**
645      * Creates a map where the keys are the property names and the values are the ElementDescriptors
646      *
647      * @param rootDescriptor the values of the maps are the children of this
648      * <code>ElementDescriptor</code> index by their property names
649      * @param map the map to which the elements will be added
650      * @deprecated 0.6 moved into XMLIntrospector
651      */

652     protected static void makeElementDescriptorMap( ElementDescriptor rootDescriptor, Map JavaDoc map ) {
653         ElementDescriptor[] children = rootDescriptor.getElementDescriptors();
654         if ( children != null ) {
655             for ( int i = 0, size = children.length; i < size; i++ ) {
656                 ElementDescriptor child = children[i];
657                 String JavaDoc propertyName = child.getPropertyName();
658                 if ( propertyName != null ) {
659                     map.put( propertyName, child );
660                 }
661                 makeElementDescriptorMap( child, map );
662             }
663         }
664     }
665
666     /**
667      * Traverse the tree of element descriptors and find the oldValue and swap it with the newValue.
668      * This would be much easier to do if ElementDescriptor supported a parent relationship.
669      *
670      * @param rootDescriptor traverse child graph for this <code>ElementDescriptor</code>
671      * @param oldValue replace this <code>ElementDescriptor</code>
672      * @param newValue replace with this <code>ElementDescriptor</code>
673      * @deprecated 0.6 now unused
674      */

675     protected static void swapDescriptor(
676                                 ElementDescriptor rootDescriptor,
677                                 ElementDescriptor oldValue,
678                                 ElementDescriptor newValue ) {
679         ElementDescriptor[] children = rootDescriptor.getElementDescriptors();
680         if ( children != null ) {
681             for ( int i = 0, size = children.length; i < size; i++ ) {
682                 ElementDescriptor child = children[i];
683                 if ( child == oldValue ) {
684                     children[i] = newValue;
685                     break;
686                 }
687                 swapDescriptor( child, oldValue, newValue );
688             }
689         }
690     }
691 }
692
Popular Tags