All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.xfire.aegis.type.AbstractTypeCreator Maven / Gradle / Ivy

package org.codehaus.xfire.aegis.type;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;

import javax.xml.namespace.QName;

import org.codehaus.xfire.XFireRuntimeException;
import org.codehaus.xfire.aegis.Holder;
import org.codehaus.xfire.aegis.type.basic.ArrayType;
import org.codehaus.xfire.aegis.type.basic.HolderType;
import org.codehaus.xfire.aegis.type.basic.ObjectType;
import org.codehaus.xfire.aegis.type.collection.CollectionType;
import org.codehaus.xfire.aegis.type.collection.MapType;
import org.codehaus.xfire.util.NamespaceHelper;
import org.codehaus.xfire.util.ServiceUtils;

/**
 * @author Hani Suleiman Date: Jun 14, 2005 Time: 11:59:57 PM
 */
public abstract class AbstractTypeCreator
    implements TypeCreator
{
    protected TypeMapping tm;

    protected AbstractTypeCreator nextCreator;

    private Configuration typeConfiguration;

	private TypeCreator parent;
    
    public TypeMapping getTypeMapping()
    {
        return tm;
    }
    
    public TypeCreator getTopCreator() {
    	TypeCreator top = this;
    	TypeCreator next = top;
    	while (next != null) {
    		top = next;
    		next = top.getParent();
    	}
    	return top;
	}

    
    public TypeCreator getParent() {
		return parent;
	}

	public void setParent(TypeCreator parent) {
		this.parent = parent;
	}

	public void setTypeMapping(TypeMapping typeMapping)
    {
        this.tm = typeMapping;

        if (nextCreator != null)
            nextCreator.setTypeMapping(tm);
    }

    public void setNextCreator(AbstractTypeCreator creator)
    {
        this.nextCreator = creator;
        nextCreator.parent = this;
    }

    protected TypeClassInfo createClassInfo(Field f)
    {
        TypeClassInfo info = createBasicClassInfo(f.getType());
        info.setDescription("field " + f.getName() + " in  " + f.getDeclaringClass());
        return info;
    }

    public TypeClassInfo createBasicClassInfo(Class typeClass)
    {
        TypeClassInfo info = new TypeClassInfo();
        info.setDescription("class '" + typeClass.getName() + '\'');
        info.setTypeClass(typeClass);

        return info;
    }

    public Type createTypeForClass(TypeClassInfo info)
    {
        Class javaType = info.getTypeClass();
        Type result = null;
        boolean newType = true;
        
        if (info.getType() != null)
        {
            result = createUserType(info);
        }
        else if (isHolder(javaType))
        {
            result = createHolderType(info);
        }
        else if (isArray(javaType))
        {
            result = createArrayType(info);
        }
        else if (isMap(javaType))
        {
            result = createMapType(info);
        }
        else if (isCollection(javaType))
        {
            result = createCollectionType(info);
        }
        else if (isEnum(javaType))
        {
            result = createEnumType(info);
        }
        else
        {
            Type type = getTypeMapping().getType(javaType);
            if (type == null)
            {
                type = createDefaultType(info);
            }
            else
            {
                newType = false;
            }
            
            result = type;
        }

        
        if (newType && !getConfiguration().isDefaultNillable())
            result.setNillable(false);
        
        return result;
    }

    protected boolean isHolder(Class javaType)
    {
        return javaType.equals(Holder.class);
    }

    protected Type createHolderType(TypeClassInfo info)
    {
        if (info.getGenericType() == null)
        {
            throw new UnsupportedOperationException("To use holder types "
                    + "you must have an XML descriptor declaring the component type.");
        }

        Class heldCls = (Class) info.getGenericType();
        info.setTypeClass(heldCls);

        Type delegate = createType(heldCls);
        HolderType type = new HolderType(delegate);
        return type;
    }

    protected boolean isArray(Class javaType)
    {
        return javaType.isArray() && !javaType.equals(byte[].class);
    }

    protected Type createUserType(TypeClassInfo info)
    {
        try
        {
            Type type = (Type) info.getType().newInstance();

            QName name = info.getTypeName();
            if (name == null)
                name = createQName(info.getTypeClass());

            type.setSchemaType(name);
            type.setTypeClass(info.getTypeClass());
            type.setTypeMapping(getTypeMapping());

            return type;
        }
        catch (InstantiationException e)
        {
            throw new XFireRuntimeException("Couldn't instantiate type classs "
                    + info.getType().getName(), e);
        }
        catch (IllegalAccessException e)
        {
            throw new XFireRuntimeException("Couldn't access type classs "
                    + info.getType().getName(), e);
        }
    }

    protected Type createArrayType(TypeClassInfo info)
    {
        ArrayType type = new ArrayType();
        type.setTypeMapping(getTypeMapping());
        type.setTypeClass(info.getTypeClass());
        type.setSchemaType(createCollectionQName(info, type.getComponentType()));
        
        if (info.getMinOccurs() != -1) type.setMinOccurs(info.getMinOccurs());
        if (info.getMaxOccurs() != -1) type.setMaxOccurs(info.getMaxOccurs());
        
        type.setFlat(info.isFlat());
        
        return type;
    }
    
    protected QName createQName(Class javaType)
    {
        String clsName = javaType.getName();

        String ns = NamespaceHelper.makeNamespaceFromClassName(clsName, "http");
        String localName = ServiceUtils.makeServiceNameFromClassName(javaType);

        return new QName(ns, localName);
    }

    protected boolean isCollection(Class javaType)
    {
        return Collection.class.isAssignableFrom(javaType);
    }

    protected Type createCollectionTypeFromGeneric(TypeClassInfo info)
    {
        Type component = getOrCreateGenericType(info);
        
        CollectionType type = new CollectionType(component);
        type.setTypeMapping(getTypeMapping());

        QName name = info.getTypeName();
        if (name == null)
            name = createCollectionQName(info, component);
        
        type.setSchemaType(name);

        type.setTypeClass(info.getTypeClass());
        
        if (info.getMinOccurs() != -1) type.setMinOccurs(info.getMinOccurs());
        if (info.getMaxOccurs() != -1) type.setMaxOccurs(info.getMaxOccurs());
        
        type.setFlat(info.isFlat());
        
        return type;
    }

    protected Type getOrCreateGenericType(TypeClassInfo info)
    {
        return createObjectType();
    }

    protected Type getOrCreateMapKeyType(TypeClassInfo info)
    {
        return createObjectType();
    }

    private Type createObjectType()
    {
        ObjectType type = new ObjectType();
        type.setSchemaType(DefaultTypeMappingRegistry.XSD_ANY);
        type.setTypeClass(Object.class);
        type.setTypeMapping(getTypeMapping());
        return type;
    }

    protected Type getOrCreateMapValueType(TypeClassInfo info)
    {
        return createObjectType();
    }
    
    protected Type createMapType(TypeClassInfo info, Type keyType, Type valueType)
    {
        QName schemaType = createMapQName(info, keyType, valueType);
        MapType type = new MapType(schemaType, keyType, valueType);
        type.setTypeMapping(getTypeMapping());
        type.setTypeClass(info.getTypeClass());

        return type;
    }

    protected Type createMapType(TypeClassInfo info)
    {
        Type keyType = getOrCreateMapKeyType(info);
        Type valueType = getOrCreateMapValueType(info);

        return createMapType(info, keyType, valueType);
    }

    protected QName createMapQName(TypeClassInfo info, Type keyType, Type valueType)
    {
        String name = keyType.getSchemaType().getLocalPart() + '2'
                + valueType.getSchemaType().getLocalPart() + "Map";

        // TODO: Get namespace from XML?
        return new QName(tm.getEncodingStyleURI(), name);
    }

    protected boolean isMap(Class javaType)
    {
        return Map.class.isAssignableFrom(javaType);
    }

    public abstract TypeClassInfo createClassInfo(PropertyDescriptor pd);

    protected boolean isEnum(Class javaType)
    {
        return false;
    }

    public Type createEnumType(TypeClassInfo info)
    {
        return null;
    }

    public abstract Type createCollectionType(TypeClassInfo info);

    public abstract Type createDefaultType(TypeClassInfo info);

    protected QName createCollectionQName(TypeClassInfo info, Type type)
    {
        String ns;

        if (type.isComplex())
        {
            ns = type.getSchemaType().getNamespaceURI();
        }
        else
        {
            ns = tm.getEncodingStyleURI();
        }

        String first = type.getSchemaType().getLocalPart().substring(0, 1);
        String last = type.getSchemaType().getLocalPart().substring(1);
        String localName = "ArrayOf" + first.toUpperCase() + last;

        return new QName(ns, localName);
    }

    public abstract TypeClassInfo createClassInfo(Method m, int index);

    /**
     * Create a Type for a Method parameter.
     * 
     * @param m
     *            the method to create a type for
     * @param index
     *            The parameter index. If the index is less than zero, the
     *            return type is used.
     */
    public Type createType(Method m, int index)
    {
        TypeClassInfo info = createClassInfo(m, index);
        info.setDescription((index == -1 ? "return type" : "parameter " + index) + " of method "
                + m.getName() + " in " + m.getDeclaringClass());
        return createTypeForClass(info);
    }
    
    public QName getElementName(Method m, int index)
    {
        TypeClassInfo info = createClassInfo(m, index);
        
        return info.getMappedName();
    }

    /**
     * Create type information for a PropertyDescriptor.
     * 
     * @param pd
     *            the propertydescriptor
     */
    public Type createType(PropertyDescriptor pd)
    {
        TypeClassInfo info = createClassInfo(pd);
        info.setDescription("property " + pd.getName());
        return createTypeForClass(info);
    }

    /**
     * Create type information for a Field.
     * 
     * @param f
     *            the field to create a type from
     */
    public Type createType(Field f)
    {
        TypeClassInfo info = createClassInfo(f);
        info.setDescription("field " + f.getName() + " in " + f.getDeclaringClass());
        return createTypeForClass(info);
    }

    public Type createType(Class clazz)
    {
        TypeClassInfo info = createBasicClassInfo(clazz);
        info.setDescription(clazz.toString());
        return createTypeForClass(info);
    }

    public Configuration getConfiguration()
    {
        return typeConfiguration;
    }

    public void setConfiguration(Configuration typeConfiguration)
    {
        this.typeConfiguration = typeConfiguration;
    }
    
    public static class TypeClassInfo
    {
        Class typeClass;

        Object[] annotations;

        Object genericType;

        Object keyType;

        QName mappedName;

        QName typeName;

        Class type;

        String description;

        long minOccurs = -1;
        long maxOccurs = -1;
        boolean flat = false;
        
        public String getDescription()
        {
            return description;
        }

        public void setDescription(String description)
        {
            this.description = description;
        }

        public Object[] getAnnotations()
        {
            return annotations;
        }

        public void setAnnotations(Object[] annotations)
        {
            this.annotations = annotations;
        }

        public Object getGenericType()
        {
            return genericType;
        }

        public void setGenericType(Object genericType)
        {
            this.genericType = genericType;
        }

        public Object getKeyType()
        {
            return keyType;
        }

        public void setKeyType(Object keyType)
        {
            this.keyType = keyType;
        }

        public Class getTypeClass()
        {
            return typeClass;
        }

        public void setTypeClass(Class typeClass)
        {
            this.typeClass = typeClass;
        }

        public QName getTypeName()
        {
            return typeName;
        }

        public void setTypeName(QName name)
        {
            this.typeName = name;
        }

        public Class getType()
        {
            return type;
        }

        public void setType(Class type)
        {
            this.type = type;
        }

        public QName getMappedName()
        {
            return mappedName;
        }

        public void setMappedName(QName mappedName)
        {
            this.mappedName = mappedName;
        }

        public long getMaxOccurs()
        {
            return maxOccurs;
        }

        public void setMaxOccurs(long maxOccurs)
        {
            this.maxOccurs = maxOccurs;
        }

        public long getMinOccurs()
        {
            return minOccurs;
        }

        public void setMinOccurs(long minOccurs)
        {
            this.minOccurs = minOccurs;
        }

        public boolean isFlat()
        {
            return flat;
        }

        public void setFlat(boolean flat)
        {
            this.flat = flat;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy