001    // Copyright 2006, 2007, 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.internal.transform;
016    
017    import org.apache.tapestry5.func.F;
018    import org.apache.tapestry5.func.Predicate;
019    import org.apache.tapestry5.ioc.ObjectLocator;
020    import org.apache.tapestry5.ioc.OperationTracker;
021    import org.apache.tapestry5.ioc.annotations.Inject;
022    import org.apache.tapestry5.model.MutableComponentModel;
023    import org.apache.tapestry5.plastic.PlasticClass;
024    import org.apache.tapestry5.plastic.PlasticField;
025    import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2;
026    import org.apache.tapestry5.services.transform.InjectionProvider2;
027    import org.apache.tapestry5.services.transform.TransformationSupport;
028    
029    /**
030     * Performs injection triggered by any field annotated with the {@link org.apache.tapestry5.ioc.annotations.Inject}
031     * annotation or the {@link javax.inject.Inject} annotation.
032     * <p/>
033     * The implementation of this worker mostly delegates to a chain of command of {@link InjectionProvider2}.
034     */
035    public class InjectWorker implements ComponentClassTransformWorker2
036    {
037        private final ObjectLocator locator;
038    
039        // Really, a chain of command
040    
041        private final InjectionProvider2 injectionProvider;
042    
043        private final OperationTracker tracker;
044    
045        private final Predicate<PlasticField> MATCHER = new Predicate<PlasticField>()
046        {
047            public boolean accept(PlasticField field)
048            {
049                return field.hasAnnotation(Inject.class) ||
050                        field.hasAnnotation(javax.inject.Inject.class);
051            }
052        };
053    
054        public InjectWorker(ObjectLocator locator, InjectionProvider2 injectionProvider, OperationTracker tracker)
055        {
056            this.locator = locator;
057            this.injectionProvider = injectionProvider;
058            this.tracker = tracker;
059        }
060    
061        public void transform(final PlasticClass plasticClass, TransformationSupport support, final MutableComponentModel model)
062        {
063            for (final PlasticField field : F.flow(plasticClass.getUnclaimedFields()).filter(MATCHER))
064            {
065                final String fieldName = field.getName();
066    
067                tracker.run(String.format("Injecting field  %s.%s", plasticClass.getClassName(), fieldName), new Runnable()
068                {
069                    public void run()
070                    {
071                        try
072                        {
073                            boolean success = injectionProvider.provideInjection(field, locator, model);
074    
075                            if (success)
076                            {
077                                field.claim("@Inject");
078                            }
079                        } catch (RuntimeException ex)
080                        {
081                            throw new RuntimeException(TransformMessages.fieldInjectionError(plasticClass.getClassName(),
082                                    fieldName, ex), ex);
083                        }
084                    }
085                });
086            }
087        }
088    }