    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    }