001// Copyright 2004, 2005 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.tapestry.enhance;
016
017import java.lang.reflect.Modifier;
018
019import org.apache.hivemind.ApplicationRuntimeException;
020import org.apache.hivemind.Location;
021import org.apache.hivemind.service.MethodSignature;
022import org.apache.hivemind.util.Defense;
023import org.apache.tapestry.services.InjectedValueProvider;
024import org.apache.tapestry.spec.InjectSpecification;
025
026/**
027 * Implementation for injection type "object" (the default). Adds read-only properties to the
028 * enhanced class that contain objects injected from HiveMind.
029 * 
030 * @author Howard M. Lewis Ship
031 * @since 4.0
032 */
033public class InjectObjectWorker implements InjectEnhancementWorker
034{
035    private InjectedValueProvider _provider;
036
037    public void performEnhancement(EnhancementOperation op, InjectSpecification is)
038    {
039        String name = is.getProperty();
040        String objectReference = is.getObject();
041        Location location = is.getLocation();
042
043        injectObject(op, objectReference, name, location);
044    }
045
046    public void injectObject(EnhancementOperation op, String objectReference, String propertyName,
047            Location location)
048    {
049        Defense.notNull(op, "op");
050        Defense.notNull(propertyName, "propertyName");
051        Defense.notNull(objectReference, "objectReference");
052
053        Class propertyType = op.getPropertyType(propertyName);
054        if (propertyType == null)
055            propertyType = Object.class;
056
057        op.claimReadonlyProperty(propertyName);
058
059        Object injectedValue = _provider.obtainValue(objectReference, location);
060
061        if (injectedValue == null)
062            throw new ApplicationRuntimeException(EnhanceMessages
063                    .locatedValueIsNull(objectReference), location, null);
064
065        if (!propertyType.isAssignableFrom(injectedValue.getClass()))
066            throw new ApplicationRuntimeException(EnhanceMessages.incompatibleInjectType(
067                    objectReference,
068                    injectedValue,
069                    propertyType), location, null);
070
071        String fieldName = op.addInjectedField("_$" + propertyName, propertyType, injectedValue);
072
073        String methodName = EnhanceUtils.createAccessorMethodName(propertyName);
074
075        op.addMethod(
076                Modifier.PUBLIC,
077                new MethodSignature(propertyType, methodName, null, null),
078                "return " + fieldName + ";", location);
079    }
080
081    public void setProvider(InjectedValueProvider provider)
082    {
083        _provider = provider;
084    }
085}