001// Copyright 2008, 2009, 2010, 2011 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007// http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.tapestry5.ioc.internal.services;
016
017import java.lang.reflect.Method;
018import java.util.Arrays;
019import java.util.Set;
020
021import org.apache.tapestry5.ioc.AnnotationAccess;
022import org.apache.tapestry5.ioc.AnnotationProvider;
023import org.apache.tapestry5.ioc.MethodAdvice;
024import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
025import org.apache.tapestry5.ioc.internal.util.InternalUtils;
026import org.apache.tapestry5.ioc.services.PlasticProxyFactory;
027import org.apache.tapestry5.plastic.PlasticClass;
028import org.apache.tapestry5.plastic.PlasticClassTransformation;
029import org.apache.tapestry5.plastic.PlasticField;
030
031@SuppressWarnings("all")
032public class AspectInterceptorBuilderImpl<T> extends AbtractAspectInterceptorBuilder<T>
033{
034    private final Class<T> serviceInterface;
035
036    private final Set<Method> allMethods = CollectionFactory.newSet();
037
038    private final PlasticClassTransformation transformation;
039
040    private final PlasticClass plasticClass;
041
042    public AspectInterceptorBuilderImpl(AnnotationAccess annotationAccess, PlasticProxyFactory plasticProxyFactory,
043            Class<T> serviceInterface, T delegate, String description)
044    {
045        super(annotationAccess);
046
047        this.serviceInterface = serviceInterface;
048
049        transformation = plasticProxyFactory.createProxyTransformation(serviceInterface);
050        plasticClass = transformation.getPlasticClass();
051
052        plasticClass.addToString(description);
053
054        allMethods.addAll(Arrays.asList(serviceInterface.getMethods()));
055
056        PlasticField delegateField = plasticClass.introduceField(serviceInterface, "delegate").inject(delegate);
057
058        for (Method method : allMethods)
059        {
060            plasticClass.introduceMethod(method).delegateTo(delegateField);
061        }
062    }
063
064    public void adviseMethod(Method method, MethodAdvice advice)
065    {
066        assert method != null;
067        assert advice != null;
068
069        AnnotationProvider methodAnnotationProvider = getMethodAnnotationProvider(method.getName(),
070                method.getParameterTypes());
071
072        adviseMethod(method, InternalUtils.toPlasticMethodAdvice(advice, methodAnnotationProvider));
073    }
074
075    public void adviseAllMethods(MethodAdvice advice)
076    {
077        for (Method m : serviceInterface.getMethods())
078            adviseMethod(m, advice);
079    }
080
081    public void adviseMethod(Method method, org.apache.tapestry5.plastic.MethodAdvice advice)
082    {
083        assert method != null;
084        assert advice != null;
085
086        if (!allMethods.contains(method))
087            throw new IllegalArgumentException(String.format("Method %s is not defined for interface %s.", method,
088                    serviceInterface));
089
090        plasticClass.introduceMethod(method).addAdvice(advice);
091    }
092
093    public void adviseAllMethods(org.apache.tapestry5.plastic.MethodAdvice advice)
094    {
095        for (Method m : serviceInterface.getMethods())
096        {
097            adviseMethod(m, advice);
098        }
099    }
100
101    public Class getInterface()
102    {
103        return serviceInterface;
104    }
105
106    public T build()
107    {
108        return (T) transformation.createInstantiator().newInstance();
109    }
110}