001// Licensed under the Apache License, Version 2.0 (the "License");
002// you may not use this file except in compliance with the License.
003// You may obtain a copy of the License at
004//
005// http://www.apache.org/licenses/LICENSE-2.0
006//
007// Unless required by applicable law or agreed to in writing, software
008// distributed under the License is distributed on an "AS IS" BASIS,
009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
010// See the License for the specific language governing permissions and
011// limitations under the License.
012
013package org.apache.tapestry5.internal.services;
014
015import org.apache.tapestry5.Asset;
016import org.apache.tapestry5.ComponentResources;
017import org.apache.tapestry5.annotations.Path;
018import org.apache.tapestry5.ioc.ObjectLocator;
019import org.apache.tapestry5.model.MutableComponentModel;
020import org.apache.tapestry5.plastic.ComputedValue;
021import org.apache.tapestry5.plastic.InstanceContext;
022import org.apache.tapestry5.plastic.PlasticField;
023import org.apache.tapestry5.services.AssetSource;
024import org.apache.tapestry5.services.transform.InjectionProvider2;
025
026/**
027 * Performs injection of assets, based on the presence of the {@link Path} annotation. This is more
028 * useful than the
029 * general {@link AssetObjectProvider}, because relative assets are supported.
030 */
031public class AssetInjectionProvider implements InjectionProvider2
032{
033    private final AssetSource assetSource;
034
035    public AssetInjectionProvider(AssetSource assetSource)
036    {
037        this.assetSource = assetSource;
038    }
039
040    public boolean provideInjection(PlasticField field, ObjectLocator locator, MutableComponentModel componentModel)
041    {
042        Path path = field.getAnnotation(Path.class);
043
044        if (path == null)
045        {
046            return false;
047        }
048
049        final String assetPath = path.value();
050        final String libraryName = componentModel.getLibraryName();
051
052        ComputedValue<Asset> computedAsset = new ComputedValue<Asset>()
053        {
054            public Asset get(InstanceContext context)
055            {
056                ComponentResources resources = context.get(ComponentResources.class);
057
058                // Note how this works: the resources represents the actual instantiated class, and the libraryName
059                // comes from the componentModel, potentially, the componentModel of a base class (which may have
060                // a different library name than the subclass).
061                return assetSource.getComponentAsset(resources, assetPath, libraryName);
062            }
063        };
064
065        field.injectComputed(computedAsset);
066
067        return true;
068    }
069
070}