FileDocCategorySizeDatePackage
TypeDesc.javaAPI DocApache Axis 1.416929Sat Apr 22 18:57:26 BST 2006org.apache.axis.description

TypeDesc

public class TypeDesc extends Object implements Serializable
A TypeDesc represents a Java<->XML data binding. It is essentially a collection of FieldDescs describing how to map each field in a Java class to XML.
author
Glen Daniels (gdaniels@apache.org)

Fields Summary
public static final Class[]
noClasses
public static final Object[]
noObjects
private static Map
classMap
A map of {class -> TypeDesc}}
private boolean
lookedForAny
Have we already introspected for the special "any" property desc?
private boolean
canSearchParents
Can this instance search for metadata in parents of the type it describes?
private boolean
hasSearchedParents
private TypeDesc
parentDesc
My superclass TypeDesc
protected static Log
log
private WeakReference
javaClassRef
WeakReference to the Java class for this type
private QName
xmlType
The XML type QName for this type
private FieldDesc[]
fields
The various fields in here
private HashMap
fieldNameMap
A cache of FieldDescs by name
private HashMap
fieldElementMap
A cache of FieldDescs by Element QName
private boolean
_hasAttributes
Are there any fields which are serialized as attributes?
private org.apache.axis.utils.BeanPropertyDescriptor[]
propertyDescriptors
Introspected property descriptors
private Map
propertyMap
Map with key = property descriptor name, value = descriptor
private org.apache.axis.utils.BeanPropertyDescriptor
anyDesc
Indication if this type has support for xsd:any.
Constructors Summary
public TypeDesc(Class javaClass)
Creates a new TypeDesc instance. The type desc can search the metadata of its type'sparent classes.

param
javaClass a Class value


                               
       
        this(javaClass, true);
    
public TypeDesc(Class javaClass, boolean canSearchParents)
Creates a new TypeDesc instance.

param
javaClass a Class value
param
canSearchParents whether the type desc can search the metadata of its type's parent classes.

        this.javaClassRef = new WeakReference(javaClass);
        this.canSearchParents = canSearchParents;
        Class cls = javaClass.getSuperclass();
        if (cls != null && !cls.getName().startsWith("java.")) {
            parentDesc = getTypeDescForClass(cls);
        }        
    
Methods Summary
public voidaddFieldDesc(FieldDesc field)
Add a new FieldDesc, keeping the convenience fields in sync.

        if (field == null) {
            throw new IllegalArgumentException(
                    Messages.getMessage("nullFieldDesc"));
        }
        
        int numFields = 0;
        if (fields != null) {
            numFields = fields.length;
        }
        FieldDesc [] newFields = new FieldDesc[numFields + 1];
        if (fields != null) {
            System.arraycopy(fields, 0, newFields, 0, numFields);
        }
        newFields[numFields] = field;
        fields = newFields;
        
        // Keep track of the field by name for fast lookup
        fieldNameMap.put(field.getFieldName(), field);
        
        if (!_hasAttributes && !field.isElement())
            _hasAttributes = true;
    
public org.apache.axis.utils.BeanPropertyDescriptorgetAnyContentDescriptor()

        if (!lookedForAny) {
            // javaClassRef is a WeakReference. So, our javaClass may have been GC'ed.
            // Protect against this case...
            Class javaClass = (Class)javaClassRef.get();
            if (javaClass != null) {
                anyDesc = BeanUtils.getAnyContentPD(javaClass);
            }
            else {
                log.error(Messages.getMessage("classGCed"));
                anyDesc = null;
            }

            lookedForAny = true;
        }
        return anyDesc;
    
public org.apache.axis.utils.BeanPropertyDescriptorgetAnyDesc()


       
        return anyDesc;
    
public javax.xml.namespace.QNamegetAttributeNameForField(java.lang.String fieldName)
Get the QName associated with this field, but only if it's marked as an attribute.

        FieldDesc desc = (FieldDesc)fieldNameMap.get(fieldName);
        if (desc == null) {
            // check superclasses if they exist
            // and we are allowed to look
            if (canSearchParents) {
                if (parentDesc != null) {
                    return parentDesc.getAttributeNameForField(fieldName);
                }
            }
        } else if (!desc.isElement()) {
            QName ret = desc.getXmlName();
            if (ret == null) {
                ret = new QName("", fieldName);
            }
            return ret;
        }
        return null;
    
public javax.xml.namespace.QNamegetElementNameForField(java.lang.String fieldName)
Get the QName associated with this field, but only if it's marked as an element.

        FieldDesc desc = (FieldDesc)fieldNameMap.get(fieldName);
        if (desc == null) {
            // check superclasses if they exist
            // and we are allowed to look
            if (canSearchParents) {
                if (parentDesc != null) {
                    return parentDesc.getElementNameForField(fieldName);
                }
            }
        } else if (desc.isElement()) {
            return desc.getXmlName();
        } 
        return null;
    
public FieldDescgetFieldByName(java.lang.String name)
Get a FieldDesc by field name.

        FieldDesc ret = (FieldDesc)fieldNameMap.get(name);
        if (ret == null && canSearchParents) {
            if (parentDesc != null) {
                ret = parentDesc.getFieldByName(name);
            }
        }
        return ret;
    
public java.lang.StringgetFieldNameForAttribute(javax.xml.namespace.QName qname)
Get the field name associated with this QName, but only if it's marked as an attribute.

        String possibleMatch = null;

        for (int i = 0; fields != null && i < fields.length; i++) {
            FieldDesc field = fields[i];
            if (!field.isElement()) {
                // It's an attribute, so if we have a solid match, return
                // its name.
                if (qname.equals(field.getXmlName())) {
                    return field.getFieldName();
                }
                // Not a solid match, but it's still possible we might match
                // the default (i.e. QName("", fieldName))
                if (qname.getNamespaceURI().equals("") &&
                    qname.getLocalPart().equals(field.getFieldName())) {
                    possibleMatch = field.getFieldName();
                }
            }
        }
        
        if (possibleMatch == null && canSearchParents) {
            // check superclasses if they exist
            // and we are allowed to look
            if (parentDesc != null) {
                possibleMatch = parentDesc.getFieldNameForAttribute(qname);
            }
        }
        
        return possibleMatch;
    
public java.lang.StringgetFieldNameForElement(javax.xml.namespace.QName qname, boolean ignoreNS)
Get the field name associated with this QName, but only if it's marked as an element. If the "ignoreNS" argument is true, just compare localNames.

        // have we already computed the answer to this question?
        if (fieldElementMap != null) {
            String cached = (String) fieldElementMap.get(qname);
            if (cached != null) return cached;
        }

        String result = null;

        String localPart = qname.getLocalPart();

        // check fields in this class
        for (int i = 0; fields != null && i < fields.length; i++) {
            FieldDesc field = fields[i];
            if (field.isElement()) {
                QName xmlName = field.getXmlName();
                if (localPart.equals(xmlName.getLocalPart())) {
                    if (ignoreNS || qname.getNamespaceURI().
                                        equals(xmlName.getNamespaceURI())) {
                        result = field.getFieldName();
                        break;
                    }
                }
            }
        }
        
        // check superclasses if they exist
        // and we are allowed to look
        if (result == null && canSearchParents) {
            if (parentDesc != null) {
                result = parentDesc.getFieldNameForElement(qname, ignoreNS);
            }
        }

        // cache the answer away for quicker retrieval next time.
        if (result != null) {
            if (fieldElementMap == null) fieldElementMap = new HashMap();
            fieldElementMap.put(qname, result);
        }

        return result;
    
public FieldDesc[]getFields()
Obtain the current array of FieldDescs

        return fields;
    
public FieldDesc[]getFields(boolean searchParents)

        // note that if canSearchParents is false, this is identical
        // to getFields(), because the parent type's metadata is off
        // limits for restricted types which are required to provide a
        // complete description of their content model in their own
        // metadata, per the XML schema rules for
        // derivation-by-restriction
        if (canSearchParents && searchParents && !hasSearchedParents) {
            // check superclasses if they exist
            if (parentDesc != null) {
                FieldDesc [] parentFields = parentDesc.getFields(true);
// START FIX http://nagoya.apache.org/bugzilla/show_bug.cgi?id=17188
                if (parentFields != null) {
                    if (fields != null) {
                        FieldDesc [] ret = new FieldDesc[parentFields.length + fields.length];
                        System.arraycopy(parentFields, 0, ret, 0, parentFields.length);
                        System.arraycopy(fields, 0, ret, parentFields.length, fields.length);
                        fields = ret;
                    } else {
                        FieldDesc [] ret = new FieldDesc[parentFields.length];
                        System.arraycopy(parentFields, 0, ret, 0, parentFields.length);
                        fields = ret;
                    }
// END FIX http://nagoya.apache.org/bugzilla/show_bug.cgi?id=17188
                }
            }
            
            hasSearchedParents = true;
        }

        return fields;
    
public java.util.MapgetPropertyDescriptorMap()
Get/Cache the property descriptor map

return
Map with key=propertyName, value=descriptor

        synchronized (this) {
            // Return map if already set.
            if (propertyMap != null) {
                return propertyMap;
            }

            // Make sure properties exist
            if (propertyDescriptors == null) {
                getPropertyDescriptors();  
            }

            // Build the map
            propertyMap = new HashMap();
            for (int i = 0; i < propertyDescriptors.length; i++) {
                BeanPropertyDescriptor descriptor = propertyDescriptors[i];
                propertyMap.put(descriptor.getName(), descriptor);
            }
        }
        return propertyMap;
    
public org.apache.axis.utils.BeanPropertyDescriptor[]getPropertyDescriptors()
Get/Cache the property descriptors

return
PropertyDescriptor

        // Return the propertyDescriptors if already set.
        // If not set, use BeanUtils.getPd to get the property descriptions.
        //
        // Since javaClass is a generated class, there
        // may be a faster way to set the property descriptions than
        // using BeanUtils.getPd.  But for now calling getPd is sufficient.
        if (propertyDescriptors == null) {
            makePropertyDescriptors();
        }
        return propertyDescriptors;
    
public static org.apache.axis.description.TypeDescgetTypeDescForClass(java.lang.Class cls)
Static function for centralizing access to type metadata for a given class. This checks for a static getTypeDesc() method on the class or _Helper class. Eventually we may extend this to provide for external metadata config (via files sitting in the classpath, etc).

        // First see if we have one explicitly registered
        // or cached from previous lookup
        TypeDesc result = (TypeDesc)classMap.get(cls);

        if (result == null) {
            try {
                Method getTypeDesc = 
                    MethodCache.getInstance().getMethod(cls, 
                                                        "getTypeDesc", 
                                                        noClasses);
                if (getTypeDesc != null) {
                    result = (TypeDesc)getTypeDesc.invoke(null, noObjects);
                    if (result != null) {
                        classMap.put(cls, result);
                    }
                }
            } catch (Exception e) {
            }
        }
        
        return result;
    
public javax.xml.namespace.QNamegetXmlType()

        return xmlType;
    
public booleanhasAttributes()
Do we have any FieldDescs marked as attributes?

        if (_hasAttributes)
            return true;
        
        if (canSearchParents) {
            if (parentDesc != null) {
                return parentDesc.hasAttributes();
            }
        }

        return false;
    
private synchronized voidmakePropertyDescriptors()

        if (propertyDescriptors != null)
            return;

        // javaClassRef is a WeakReference. So, our javaClass may have been GC'ed.
        // Protect against this case...
        Class javaClass = (Class)javaClassRef.get();
        if (javaClass == null) {
            // could throw a RuntimeException, but instead log error and dummy up descriptors
            log.error(Messages.getMessage("classGCed"));
            propertyDescriptors = new BeanPropertyDescriptor[0];
            anyDesc = null;
            lookedForAny = true;
            return;
        }

        propertyDescriptors = BeanUtils.getPd(javaClass, this);
        if (!lookedForAny) {
            anyDesc = BeanUtils.getAnyContentPD(javaClass);
            lookedForAny = true;
        }
    
public static voidregisterTypeDescForClass(java.lang.Class cls, org.apache.axis.description.TypeDesc td)
Static function to explicitly register a type description for a given class.

param
cls the Class we're registering metadata about
param
td the TypeDesc containing the metadata

        classMap.put(cls, td);
    
public voidsetFields(FieldDesc[] newFields)
Replace the array of FieldDescs, making sure we keep our convenience caches in sync.

        fieldNameMap = new HashMap();
        fields = newFields;
        _hasAttributes = false;
        fieldElementMap = null;
        
        for (int i = 0; i < newFields.length; i++) {
            FieldDesc field = newFields[i];
            if (!field.isElement()) {
                _hasAttributes = true;
            }
            fieldNameMap.put(field.getFieldName(), field);
        }
    
public voidsetXmlType(javax.xml.namespace.QName xmlType)

        this.xmlType = xmlType;