001    // Copyright 2009, 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    
015    package org.apache.tapestry5.ioc.internal;
016    
017    import java.util.List;
018    
019    import org.apache.tapestry5.ioc.ObjectCreator;
020    import org.apache.tapestry5.ioc.ServiceAdvisor;
021    import org.apache.tapestry5.ioc.def.ServiceDef3;
022    import org.apache.tapestry5.ioc.services.AspectDecorator;
023    import org.apache.tapestry5.ioc.services.AspectInterceptorBuilder;
024    
025    /**
026     * Equivalent of {@link org.apache.tapestry5.ioc.internal.InterceptorStackBuilder}, but works using an
027     * {@link org.apache.tapestry5.ioc.services.AspectInterceptorBuilder} that receives advice from
028     * {@link org.apache.tapestry5.ioc.ServiceAdvisor}s.
029     * 
030     * @since 5.1.0.0
031     */
032    public class AdvisorStackBuilder implements ObjectCreator
033    {
034        private final ServiceDef3 serviceDef;
035    
036        private final ObjectCreator delegate;
037    
038        private final AspectDecorator aspectDecorator;
039    
040        private final InternalRegistry registry;
041    
042        /**
043         * @param serviceDef
044         *            the service that is ultimately being constructed
045         * @param delegate
046         *            responsible for creating the object to be decorated
047         * @param aspectDecorator
048         *            used to create the {@link org.apache.tapestry5.ioc.services.AspectInterceptorBuilder} passed to each
049         *            {@link org.apache.tapestry5.ioc.ServiceAdvisor}
050         * @param registry
051         */
052        public AdvisorStackBuilder(ServiceDef3 serviceDef, ObjectCreator delegate, AspectDecorator aspectDecorator,
053                InternalRegistry registry)
054        {
055            this.serviceDef = serviceDef;
056            this.delegate = delegate;
057            this.registry = registry;
058            this.aspectDecorator = aspectDecorator;
059        }
060    
061        public Object createObject()
062        {
063            Object service = delegate.createObject();
064    
065            List<ServiceAdvisor> advisors = registry.findAdvisorsForService(serviceDef);
066    
067            if (advisors.isEmpty())
068                return service;
069    
070            final AspectInterceptorBuilder builder = aspectDecorator.createBuilder(serviceDef.getServiceInterface(),
071                    service, serviceDef, String.format("<AspectProxy for %s(%s)>", serviceDef.getServiceId(), serviceDef
072                            .getServiceInterface().getName()));
073    
074            for (final ServiceAdvisor advisor : advisors)
075            {
076                registry.run("Invoking " + advisor, new Runnable()
077                {
078                    public void run()
079                    {
080                        advisor.advise(builder);
081                    }
082                });
083            }
084    
085            return builder.build();
086        }
087    }