📄 xmlintrospector.java
字号:
Map elementsByPropertyName = makeElementDescriptorMap( rootDescriptor );
for (Iterator it=singleParameterAdders.iterator();it.hasNext();) {
Method singleParameterAdder = (Method) it.next();
setIteratorAdder(elementsByPropertyName, singleParameterAdder);
}
for (Iterator it=twinParameterAdders.iterator();it.hasNext();) {
Method twinParameterAdder = (Method) it.next();
setMapAdder(elementsByPropertyName, twinParameterAdder);
}
}
}
/**
* Sets the adder method where the corresponding property is an iterator
* @param rootDescriptor
* @param singleParameterAdder
*/
private void setIteratorAdder(
Map elementsByPropertyName,
Method singleParameterAdderMethod) {
String adderName = singleParameterAdderMethod.getName();
String propertyName = Introspector.decapitalize(adderName.substring(3));
ElementDescriptor matchingDescriptor = getMatchForAdder(propertyName, elementsByPropertyName);
if (matchingDescriptor != null) {
//TODO defensive code: probably should check descriptor type
Class singularType = singleParameterAdderMethod.getParameterTypes()[0];
if (getLog().isTraceEnabled()) {
getLog().trace(adderName + "->" + propertyName);
}
// this may match a standard collection or iteration
getLog().trace("Matching collection or iteration");
matchingDescriptor.setUpdater( new MethodUpdater( singleParameterAdderMethod ) );
matchingDescriptor.setSingularPropertyType( singularType );
matchingDescriptor.setHollow(!isPrimitiveType(singularType));
String localName = matchingDescriptor.getLocalName();
if ( localName == null || localName.length() == 0 ) {
matchingDescriptor.setLocalName(
getElementNameMapper()
.mapTypeToElementName( propertyName ) );
}
if ( getLog().isDebugEnabled() ) {
getLog().debug( "!! " + singleParameterAdderMethod);
getLog().debug( "!! " + singularType);
}
}
}
/**
* Sets the adder where the corresponding property type is an map
* @param rootDescriptor
* @param singleParameterAdder
*/
private void setMapAdder(
Map elementsByPropertyName,
Method twinParameterAdderMethod) {
String adderName = twinParameterAdderMethod.getName();
String propertyName = Introspector.decapitalize(adderName.substring(3));
ElementDescriptor matchingDescriptor = getMatchForAdder(propertyName, elementsByPropertyName);
if ( matchingDescriptor != null
&& Map.class.isAssignableFrom( matchingDescriptor.getPropertyType() )) {
// this may match a map
getLog().trace("Matching map");
ElementDescriptor[] children
= matchingDescriptor.getElementDescriptors();
// see if the descriptor's been set up properly
if ( children.length == 0 ) {
getLog().info(
"'entry' descriptor is missing for map. "
+ "Updaters cannot be set");
} else {
Class[] types = twinParameterAdderMethod.getParameterTypes();
Class keyType = types[0];
Class valueType = types[1];
// loop through children
// adding updaters for key and value
MapEntryAdder adder = new MapEntryAdder(twinParameterAdderMethod);
for (
int n=0,
noOfGrandChildren = children.length;
n < noOfGrandChildren;
n++ ) {
if ( "key".equals( children[n].getLocalName() ) ) {
children[n].setUpdater( adder.getKeyUpdater() );
children[n].setSingularPropertyType( keyType );
if (children[n].getPropertyType() == null) {
children[n].setPropertyType( valueType );
}
if ( isPrimitiveType(keyType) ) {
children[n].setHollow(false);
}
if ( getLog().isTraceEnabled() ) {
getLog().trace( "Key descriptor: " + children[n]);
}
} else if ( "value".equals( children[n].getLocalName() ) ) {
children[n].setUpdater( adder.getValueUpdater() );
children[n].setSingularPropertyType( valueType );
if (children[n].getPropertyType() == null) {
children[n].setPropertyType( valueType );
}
if ( isPrimitiveType( valueType) ) {
children[n].setHollow(false);
}
if ( isLoopType( valueType )) {
// need to attach a hollow descriptor
// don't know the element name
// so use null name (to match anything)
ElementDescriptor loopDescriptor = new ElementDescriptor();
loopDescriptor.setHollow(true);
loopDescriptor.setSingularPropertyType( valueType );
loopDescriptor.setPropertyType( valueType );
children[n].addElementDescriptor(loopDescriptor);
}
if ( getLog().isTraceEnabled() ) {
getLog().trace( "Value descriptor: " + children[n]);
}
}
}
}
}
}
/**
* Gets an ElementDescriptor for the property matching the adder
* @param adderName
* @param rootDescriptor
* @return
*/
private ElementDescriptor getMatchForAdder(
String propertyName,
Map elementsByPropertyName) {
ElementDescriptor matchingDescriptor = null;
if (propertyName.length() > 0) {
if ( getLog().isTraceEnabled() ) {
getLog().trace( "findPluralDescriptor( " + propertyName
+ " ):root property name=" + propertyName );
}
PluralStemmer stemmer = getPluralStemmer();
matchingDescriptor = stemmer.findPluralDescriptor( propertyName, elementsByPropertyName );
if ( getLog().isTraceEnabled() ) {
getLog().trace(
"findPluralDescriptor( " + propertyName
+ " ):ElementDescriptor=" + matchingDescriptor );
}
}
return matchingDescriptor;
}
// Implementation methods
//-------------------------------------------------------------------------
/**
* Creates a map where the keys are the property names and the values are the ElementDescriptors
*/
private Map makeElementDescriptorMap( ElementDescriptor rootDescriptor ) {
Map result = new HashMap();
String rootPropertyName = rootDescriptor.getPropertyName();
if (rootPropertyName != null) {
result.put(rootPropertyName, rootDescriptor);
}
makeElementDescriptorMap( rootDescriptor, result );
return result;
}
/**
* Creates a map where the keys are the property names and the values are the ElementDescriptors
*
* @param rootDescriptor the values of the maps are the children of this
* <code>ElementDescriptor</code> index by their property names
* @param map the map to which the elements will be added
*/
private void makeElementDescriptorMap( ElementDescriptor rootDescriptor, Map map ) {
ElementDescriptor[] children = rootDescriptor.getElementDescriptors();
if ( children != null ) {
for ( int i = 0, size = children.length; i < size; i++ ) {
ElementDescriptor child = children[i];
String propertyName = child.getPropertyName();
if ( propertyName != null ) {
map.put( propertyName, child );
}
makeElementDescriptorMap( child, map );
}
}
}
/**
* A Factory method to lazily create a new strategy
* to detect matching singular and plural properties.
*
* @return new defualt PluralStemmer implementation
* @deprecated 0.6 this method has been moved into IntrospectionConfiguration.
* Those who need to vary this should subclass that class instead
*/
protected PluralStemmer createPluralStemmer() {
return new DefaultPluralStemmer();
}
/**
* A Factory method to lazily create a strategy
* used to convert bean type names into element names.
*
* @return new default NameMapper implementation
* @deprecated 0.6 this method has been moved into IntrospectionConfiguration.
* Those who need to vary this should subclass that class instead
*/
protected NameMapper createNameMapper() {
return new DefaultNameMapper();
}
/**
* Attempt to lookup the XML descriptor for the given class using the
* classname + ".betwixt" using the same ClassLoader used to load the class
* or return null if it could not be loaded
*
* @param aClass digester .betwixt file for this class
* @return XMLBeanInfo digested from the .betwixt file if one can be found.
* Otherwise null.
*/
protected synchronized XMLBeanInfo findByXMLDescriptor( Class aClass ) {
// trim the package name
String name = aClass.getName();
int idx = name.lastIndexOf( '.' );
if ( idx >= 0 ) {
name = name.substring( idx + 1 );
}
name += ".betwixt";
URL url = aClass.getResource( name );
if ( url != null ) {
try {
String urlText = url.toString();
if ( getLog().isDebugEnabled( )) {
getLog().debug( "Parsing Betwixt XML descriptor: " + urlText );
}
// synchronized method so this digester is only used by
// one thread at once
if ( digester == null ) {
digester = new XMLBeanInfoDigester();
digester.setXMLIntrospector( this );
}
digester.setBeanClass( aClass );
return (XMLBeanInfo) digester.parse( urlText );
} catch (Exception e) {
getLog().warn( "Caught exception trying to parse: " + name, e );
}
}
if ( getLog().isTraceEnabled() ) {
getLog().trace( "Could not find betwixt file " + name );
}
return null;
}
/**
* Loop through properties and process each one
*
* @param beanInfo the BeanInfo whose properties will be processed
* @param elements ElementDescriptor list to which elements will be added
* @param attributes AttributeDescriptor list to which attributes will be added
* @param contents Descriptor list to which mixed content will be added
* @throws IntrospectionException if the bean introspection fails
* @deprecated 0.5 use {@link #addProperties(BeanProperty[], List, List,List)}
*/
protected void addProperties(
BeanInfo beanInfo,
List elements,
List attributes,
List contents)
throws
IntrospectionException {
PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
if ( descriptors != null ) {
for ( int i = 0, size = descriptors.length; i < size; i++ ) {
addProperty(beanInfo, descriptors[i], elements, attributes, contents);
}
}
if (getLog().isTraceEnabled()) {
getLog().trace(elements);
getLog().trace(attributes);
getLog().trace(contents);
}
}
/**
* Loop through properties and process each one
*
* @param beanProperties the properties to be processed
* @param elements ElementDescriptor list to which elements will be added
* @param attributes AttributeDescriptor list to which attributes will be added
* @param contents Descriptor list to which mixed content will be added
* @since 0.5
*/
protected void addProperties(
BeanProperty[] beanProperties,
List elements,
List attributes,
List contents) {
if ( beanProperties != null ) {
if (getLog().isTraceEnabled()) {
getLog().trace(beanProperties.length + " properties to be added");
}
for ( int i = 0, size = beanProperties.length; i < size; i++ ) {
addProperty(beanProperties[i], elements, attributes, contents);
}
}
if (getLog().isTraceEnabled()) {
getLog().trace("After properties have been added (elements, attributes, contents):");
getLog().trace(elements);
getLog().trace(attributes);
getLog().trace(contents);
}
}
/**
* Process a property.
* Go through and work out whether it's a loop property, a primitive or a standard.
* The class property is ignored.
*
* @param beanInfo the BeanInfo whose property is being processed
* @param propertyDescriptor the PropertyDescriptor to process
* @param elements ElementDescriptor list to which elements will be added
* @param attributes AttributeDescriptor list to which attributes will be added
* @param contents Descriptor list to which mixed content will be added
* @throws IntrospectionException if the bean introspection fails
* @deprecated 0.5 BeanInfo is no longer required.
* Use {@link #addProperty(PropertyDescriptor, List, List, List)} instead.
*/
protected void addProperty(
BeanInfo beanInfo,
PropertyDescriptor propertyDescriptor,
List elements,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -