Package org.mule.config.transformer

Source Code of org.mule.config.transformer.AnnotatedTransformerProxy

/*
* $Id: AnnotatedTransformerProxy.java 20321 2010-11-24 15:21:24Z dfeist $
* --------------------------------------------------------------------------------------
* Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
*
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.config.transformer;

import org.mule.api.MuleMessage;
import org.mule.api.annotations.param.Payload;
import org.mule.api.lifecycle.InitialisationException;
import org.mule.api.transformer.DataType;
import org.mule.api.transformer.DiscoverableTransformer;
import org.mule.api.transformer.TransformerException;
import org.mule.config.expression.ExpressionAnnotationsHelper;
import org.mule.config.i18n.AnnotationsMessages;
import org.mule.expression.transformers.ExpressionTransformer;
import org.mule.transformer.AbstractMessageTransformer;
import org.mule.transformer.types.DataTypeFactory;
import org.mule.transformer.types.SimpleDataType;
import org.mule.util.annotation.AnnotationUtils;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.WeakHashMap;

/**
* Creates a Mule {@link org.mule.api.transformer.Transformer} proxy around a transform method. The
* transformer will be given a generated name which is the short name of the class and the method name
* separated with a '.' i.e. 'MyTransformers.fooToBar'
*/
public class AnnotatedTransformerProxy extends AbstractMessageTransformer implements DiscoverableTransformer
{
    private int weighting;

    private Object proxy;

    private Method transformMethod;
    private boolean messageAware = false;
    private ExpressionTransformer paramTransformer = null;
    private Collection<TransformerArgumentResolver> resolvers;
    private Map<Class<?>, Object> cachedObjects = new WeakHashMap<Class<?>, Object>();
    private boolean sourceAnnotated = false;

    public AnnotatedTransformerProxy(int weighting, Object proxy, Method transformMethod, Class[] additionalSourceTypes, String sourceMimeType, String resultMimeType) throws TransformerException, InitialisationException
    {
        this.weighting = weighting;
        this.proxy = proxy;

        //By default we allow a transformer to return null
        setAllowNullReturn(true);

        validateMethod(transformMethod, additionalSourceTypes);

        this.transformMethod = transformMethod;
        setReturnDataType(DataTypeFactory.createFromReturnType(transformMethod));

        messageAware = MuleMessage.class.isAssignableFrom(transformMethod.getParameterTypes()[0]);
        this.transformMethod = transformMethod;
        if (additionalSourceTypes.length > 0)
        {
            if (messageAware)
            {
                logger.error("Transformer: " + getName() + " is MuleMessage aware, this means additional source types configured on the transformer will be ignorred. Source types are: " + Arrays.toString(additionalSourceTypes));
            }
            else
            {
                for (int i = 0; i < additionalSourceTypes.length; i++)
                {
                    registerSourceType(new SimpleDataType(additionalSourceTypes[i], sourceMimeType));

                }
            }
        }
        //The first Param is the always the object to transform
        Class<?> source = transformMethod.getParameterTypes()[0];
        registerSourceType(DataTypeFactory.create(source));
        sourceAnnotated = (transformMethod.getParameterAnnotations()[0].length > 0 &&
                transformMethod.getParameterAnnotations()[0][0] instanceof Payload);

        setName(proxy.getClass().getSimpleName() + "." + transformMethod.getName());
    }

    protected void validateMethod(Method method, Class[] sourceTypes) throws IllegalArgumentException
    {
        int mods = method.getModifiers();
        if(Modifier.isAbstract(mods) || Modifier.isInterface(mods) || !Modifier.isPublic(mods)
                || method.getReturnType().equals(Void.TYPE) || method.getParameterTypes().length==0 ||
                method.getReturnType().equals(Object.class) || Arrays.asList(method.getParameterTypes()).contains(Object.class) ||
                Arrays.asList(sourceTypes).contains(Object.class))
        {
            //May lift the ban on OBject return and source types
            //The details as to why the method is invalid are in the message
            throw new IllegalArgumentException(AnnotationsMessages.transformerMethodNotValid(method).getMessage());
        }
    }

    @Override
    public void initialise() throws InitialisationException
    {
        super.initialise();
        if (AnnotationUtils.methodHasParamAnnotations(transformMethod))
        {
            try
            {
                paramTransformer = ExpressionAnnotationsHelper.getTransformerForMethodWithAnnotations(transformMethod, muleContext);
            }
            catch (TransformerException e)
            {
                throw new InitialisationException(e, this);
            }
        }
        resolvers = muleContext.getRegistry().lookupObjects(TransformerArgumentResolver.class);
    }

    @Override
    public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException
    {
        Object firstArg = null;
        Object[] params = new Object[transformMethod.getParameterTypes().length];
        int paramCounter = 0;

        //the param transformer will convert the message to one or more objects depending on the annotations on the method
        //parameter
        if (paramTransformer != null)
        {
            Object paramArgs = paramTransformer.transformMessage(message, outputEncoding);

            if (paramArgs != null && paramArgs.getClass().isArray())
            {
                Object[] temp = (Object[]) paramArgs;
                //if the source is annotated, the paramTransformer will figure out the first parameter
                if (!sourceAnnotated)
                {
                    paramCounter++;
                }
                for (int i = 0; i < temp.length; i++)
                {
                    params[paramCounter++] = temp[i];
                }
            }
            else
            {
                //if the source is annotated, the paramTransformer will figure out the first parameter
                if (!sourceAnnotated)
                {
                    paramCounter++;
                }
                params[paramCounter++] = paramArgs;
            }
        }

        if (messageAware)
        {
            firstArg = message;
        }
        else if (!sourceAnnotated)
        {
            //This will perform any additional transformation from the source type to the method parameter type
            try
            {
                firstArg = message.getPayload(DataTypeFactory.create(transformMethod.getParameterTypes()[0]));
            }
            catch (TransformerException e)
            {
                throw new TransformerException(e.getI18nMessage(), this, e);
            }
        }

        //if the source is annotated, the paramTransformer will figure out the first parameter
        if (!sourceAnnotated)
        {
            params[0] = firstArg;
            if (paramCounter == 0)
            {
                paramCounter++;
            }
        }
        //Lets see if there are any context objects to inject (i.e. JAXB)
        if (paramCounter < transformMethod.getParameterTypes().length)
        {
            for (int i = paramCounter; i < transformMethod.getParameterTypes().length; i++)
            {
                Object o;
                Class<?> type = transformMethod.getParameterTypes()[i];
                o = cachedObjects.get(type);
                if (o != null)
                {
                    params[paramCounter++] = o;
                    continue;
                }
                DataType<?> source = DataTypeFactory.createFromParameterType(transformMethod, 0);

                for (TransformerArgumentResolver resolver : resolvers)
                {
                    try
                    {
                        o = resolver.resolve(type, source, this.returnType, muleContext);
                        if (o != null)
                        {
                            params[paramCounter++] = o;
                            cachedObjects.put(type, o);
                            break;
                        }
                    }
                    catch (Exception e)
                    {
                        throw new TransformerException(this, e);
                    }

                }
                if (o == null)
                {
                    throw new IllegalArgumentException("Failed to find resolver for object type: " + type + " for transform method: " + transformMethod);
                }
            }
        }
        try
        {
            return transformMethod.invoke(proxy, params);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            throw new TransformerException(this, e);
        }
    }

    public int getPriorityWeighting()
    {
        return weighting;
    }

    public void setPriorityWeighting(int weighting)
    {
        throw new UnsupportedOperationException("setPriorityWeighting");
    }

    @Override
    public boolean equals(Object o)
    {
        if (this == o)
        {
            return true;
        }
        if (o == null || getClass() != o.getClass())
        {
            return false;
        }

        AnnotatedTransformerProxy that = (AnnotatedTransformerProxy) o;

        if (messageAware != that.messageAware)
        {
            return false;
        }
        if (weighting != that.weighting)
        {
            return false;
        }
        if (proxy != null ? !proxy.equals(that.proxy) : that.proxy != null)
        {
            return false;
        }
        if (transformMethod != null ? !transformMethod.equals(that.transformMethod) : that.transformMethod != null)
        {
            return false;
        }

        return true;
    }

    @Override
    public int hashCode()
    {
        int result = weighting;
        result = 31 * result + (proxy != null ? proxy.hashCode() : 0);
        result = 31 * result + (transformMethod != null ? transformMethod.hashCode() : 0);
        result = 31 * result + (messageAware ? 1 : 0);
        return result;
    }


}
TOP

Related Classes of org.mule.config.transformer.AnnotatedTransformerProxy

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.