📄 xmlintrospector.java
字号:
* @param nameMapper the NameMapper to use for the convertion
* @deprecated 0.6 use getConfiguration().setAttributeNameMapper
*/
public void setAttributeNameMapper(NameMapper nameMapper) {
getConfiguration().setAttributeNameMapper( nameMapper );
}
/**
* Should the original <code>java.reflect.Introspector</code> bean info search path be used?
* By default it will be false.
*
* @return boolean if the beanInfoSearchPath should be used.
* @deprecated 0.6 use getConfiguration().useBeanInfoSearchPath
*/
public boolean useBeanInfoSearchPath() {
return getConfiguration().useBeanInfoSearchPath();
}
/**
* Specifies if you want to use the beanInfoSearchPath
* @see java.beans.Introspector for more details
* @param useBeanInfoSearchPath
* @deprecated 0.6 use getConfiguration().setUseBeanInfoSearchPath
*/
public void setUseBeanInfoSearchPath(boolean useBeanInfoSearchPath) {
getConfiguration().setUseBeanInfoSearchPath( useBeanInfoSearchPath );
}
// Methods
//-------------------------------------------------------------------------
/**
* Flush existing cached <code>XMLBeanInfo</code>'s.
*
* @deprecated 0.5 use flushable registry instead
*/
public void flushCache() {}
/** Create a standard <code>XMLBeanInfo</code> by introspection
* The actual introspection depends only on the <code>BeanInfo</code>
* associated with the bean.
*
* @param bean introspect this bean
* @return XMLBeanInfo describing bean-xml mapping
* @throws IntrospectionException when the bean introspection fails
*/
public XMLBeanInfo introspect(Object bean) throws IntrospectionException {
if (getLog().isDebugEnabled()) {
getLog().debug( "Introspecting..." );
getLog().debug(bean);
}
if ( bean instanceof DynaBean ) {
// allow DynaBean implementations to be overridden by .betwixt files
XMLBeanInfo xmlBeanInfo = findByXMLDescriptor( bean.getClass() );
if (xmlBeanInfo != null) {
return xmlBeanInfo;
}
// this is DynaBean use the DynaClass for introspection
return introspect( ((DynaBean) bean).getDynaClass() );
} else {
// normal bean so normal introspection
Class normalClass = getClassNormalizer().getNormalizedClass( bean );
return introspect( normalClass );
}
}
/**
* Creates XMLBeanInfo by reading the DynaProperties of a DynaBean.
* Customizing DynaBeans using betwixt is not supported.
*
* @param dynaClass the DynaBean to introspect
*
* @return XMLBeanInfo for the DynaClass
*/
public XMLBeanInfo introspect(DynaClass dynaClass) {
// for now this method does not do much, since XMLBeanInfoRegistry cannot
// use a DynaClass as a key
// TODO: add caching for DynaClass XMLBeanInfo
// need to work out if this is possible
// this line allows subclasses to change creation strategy
XMLBeanInfo xmlInfo = createXMLBeanInfo( dynaClass );
// populate the created info with
DynaClassBeanType beanClass = new DynaClassBeanType( dynaClass );
populate( xmlInfo, beanClass );
return xmlInfo;
}
/** Create a standard <code>XMLBeanInfo</code> by introspection.
* The actual introspection depends only on the <code>BeanInfo</code>
* associated with the bean.
*
* @param aClass introspect this class
* @return XMLBeanInfo describing bean-xml mapping
* @throws IntrospectionException when the bean introspection fails
*/
public XMLBeanInfo introspect(Class aClass) throws IntrospectionException {
// we first reset the beaninfo searchpath.
String[] searchPath = null;
if ( !getConfiguration().useBeanInfoSearchPath() ) {
searchPath = Introspector.getBeanInfoSearchPath();
Introspector.setBeanInfoSearchPath(new String[] { });
}
XMLBeanInfo xmlInfo = registry.get( aClass );
if ( xmlInfo == null ) {
// lets see if we can find an XML descriptor first
if ( getLog().isDebugEnabled() ) {
getLog().debug( "Attempting to lookup an XML descriptor for class: " + aClass );
}
xmlInfo = findByXMLDescriptor( aClass );
if ( xmlInfo == null ) {
BeanInfo info = Introspector.getBeanInfo( aClass );
xmlInfo = introspect( info );
}
if ( xmlInfo != null ) {
registry.put( aClass, xmlInfo );
}
} else {
getLog().trace( "Used cached XMLBeanInfo." );
}
if ( getLog().isTraceEnabled() ) {
getLog().trace( xmlInfo );
}
if ( !getConfiguration().useBeanInfoSearchPath() ) {
// we restore the beaninfo searchpath.
Introspector.setBeanInfoSearchPath( searchPath );
}
return xmlInfo;
}
/** Create a standard <code>XMLBeanInfo</code> by introspection.
* The actual introspection depends only on the <code>BeanInfo</code>
* associated with the bean.
*
* @param beanInfo the BeanInfo the xml-bean mapping is based on
* @return XMLBeanInfo describing bean-xml mapping
* @throws IntrospectionException when the bean introspection fails
*/
public XMLBeanInfo introspect(BeanInfo beanInfo) throws IntrospectionException {
XMLBeanInfo xmlBeanInfo = createXMLBeanInfo( beanInfo );
populate( xmlBeanInfo, new JavaBeanType( beanInfo ) );
return xmlBeanInfo;
}
/**
* Populates the given <code>XMLBeanInfo</code> based on the given type of bean.
*
* @param xmlBeanInfo populate this, not null
* @param bean the type definition for the bean, not null
*/
private void populate(XMLBeanInfo xmlBeanInfo, BeanType bean) {
String name = bean.getBeanName();
ElementDescriptor elementDescriptor = new ElementDescriptor();
elementDescriptor.setLocalName(
getElementNameMapper().mapTypeToElementName( name ) );
elementDescriptor.setPropertyType( bean.getElementType() );
if (getLog().isTraceEnabled()) {
getLog().trace("Populating:" + bean);
}
// add default string value for primitive types
if ( bean.isPrimitiveType() ) {
getLog().trace("Bean is primitive");
elementDescriptor.setTextExpression( StringExpression.getInstance() );
} else if ( bean.isLoopType() ) {
getLog().trace("Bean is loop");
ElementDescriptor loopDescriptor = new ElementDescriptor();
loopDescriptor.setContextExpression(
new IteratorExpression( EmptyExpression.getInstance() )
);
if ( bean.isMapType() ) {
loopDescriptor.setQualifiedName( "entry" );
}
elementDescriptor.setElementDescriptors( new ElementDescriptor[] { loopDescriptor } );
} else {
getLog().trace("Bean is standard type");
List elements = new ArrayList();
List attributes = new ArrayList();
List contents = new ArrayList();
addProperties( bean.getProperties(), elements, attributes, contents );
int size = elements.size();
if ( size > 0 ) {
ElementDescriptor[] descriptors = new ElementDescriptor[size];
elements.toArray( descriptors );
elementDescriptor.setElementDescriptors( descriptors );
}
size = attributes.size();
if ( size > 0 ) {
AttributeDescriptor[] descriptors = new AttributeDescriptor[size];
attributes.toArray( descriptors );
elementDescriptor.setAttributeDescriptors( descriptors );
}
size = contents.size();
if ( size > 0 ) {
if ( size > 0 ) {
Descriptor[] descriptors = new Descriptor[size];
contents.toArray( descriptors );
elementDescriptor.setContentDescriptors( descriptors );
}
}
}
xmlBeanInfo.setElementDescriptor( elementDescriptor );
// default any addProperty() methods
defaultAddMethods( elementDescriptor, bean.getElementType() );
if (getLog().isTraceEnabled()) {
getLog().trace("Populated descriptor:");
getLog().trace(elementDescriptor);
}
}
/**
* Creates XMLBeanInfo for the given DynaClass.
*
* @param dynaClass the class describing a DynaBean
*
* @return XMLBeanInfo that describes the properties of the given
* DynaClass
*/
protected XMLBeanInfo createXMLBeanInfo(DynaClass dynaClass) {
// XXX is the chosen class right?
XMLBeanInfo beanInfo = new XMLBeanInfo(dynaClass.getClass());
return beanInfo;
}
/**
* Create a XML descriptor from a bean one.
* Go through and work out whether it's a loop property, a primitive or a standard.
* The class property is ignored.
*
* @param propertyDescriptor create a <code>NodeDescriptor</code> for this property
* @param useAttributesForPrimitives write primitives as attributes (rather than elements)
* @return a correctly configured <code>NodeDescriptor</code> for the property
* @throws IntrospectionException when bean introspection fails
* @deprecated 0.5 use {@link #createXMLDescriptor}.
*/
public Descriptor createDescriptor(
PropertyDescriptor propertyDescriptor,
boolean useAttributesForPrimitives
) throws IntrospectionException {
return createXMLDescriptor( new BeanProperty( propertyDescriptor ) );
}
/**
* Create a XML descriptor from a bean one.
* Go through and work out whether it's a loop property, a primitive or a standard.
* The class property is ignored.
*
* @param beanProperty the BeanProperty specifying the property
* @return a correctly configured <code>NodeDescriptor</code> for the property
* @since 0.5
*/
public Descriptor createXMLDescriptor( BeanProperty beanProperty ) {
return beanProperty.createXMLDescriptor( configuration );
}
/**
* Add any addPropety(PropertyType) methods as Updaters
* which are often used for 1-N relationships in beans.
* <br>
* The tricky part here is finding which ElementDescriptor corresponds
* to the method. e.g. a property 'items' might have an Element descriptor
* which the method addItem() should match to.
* <br>
* So the algorithm we'll use
* by default is to take the decapitalized name of the property being added
* and find the first ElementDescriptor that matches the property starting with
* the string. This should work for most use cases.
* e.g. addChild() would match the children property.
* <br>
* TODO this probably needs refactoring. It probably belongs in the bean wrapper
* (so that it'll work properly with dyna-beans) and so that the operations can
* be optimized by caching. Multiple hash maps are created and getMethods is
* called multiple times. This is relatively expensive and so it'd be better
* to push into a proper class and cache.
* <br>
* TODO this probably does work properly with DynaBeans: need to push
* implementation into an class and expose it on BeanType.
*
* @param introspector use this <code>XMLIntrospector</code> for introspection
* @param rootDescriptor add defaults to this descriptor
* @param beanClass the <code>Class</code> to which descriptor corresponds
*/
public void defaultAddMethods(
ElementDescriptor rootDescriptor,
Class beanClass ) {
// lets iterate over all methods looking for one of the form
// add*(PropertyType)
if ( beanClass != null ) {
ArrayList singleParameterAdders = new ArrayList();
ArrayList twinParameterAdders = new ArrayList();
Method[] methods = beanClass.getMethods();
for ( int i = 0, size = methods.length; i < size; i++ ) {
Method method = methods[i];
String name = method.getName();
if ( name.startsWith( "add" )) {
// TODO: should we filter out non-void returning methods?
// some beans will return something as a helper
Class[] types = method.getParameterTypes();
if ( types != null) {
if ( getLog().isTraceEnabled() ) {
getLog().trace("Searching for match for " + method);
}
switch (types.length)
{
case 1:
singleParameterAdders.add(method);
break;
case 2:
twinParameterAdders.add(method);
break;
default:
// ignore
break;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -