001// Copyright 2006, 2008, 2009 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.tapestry5.internal.bindings;
016
017import org.apache.tapestry5.PropertyConduit;
018import org.apache.tapestry5.internal.TapestryInternalUtils;
019import org.apache.tapestry5.internal.services.Invariant;
020import org.apache.tapestry5.ioc.Location;
021import org.apache.tapestry5.ioc.internal.util.TapestryException;
022
023import java.lang.annotation.Annotation;
024
025/**
026 * Base class for bindings created by the {@link org.apache.tapestry5.internal.bindings.PropBindingFactory}. A subclass
027 * of this is created at runtime.
028 */
029public class PropBinding extends AbstractBinding implements InternalPropBinding
030{
031    private final Object root;
032
033    private final PropertyConduit conduit;
034
035    private final String toString;
036
037    private boolean invariant;
038    
039    private final String expression;
040
041    public PropBinding(final Location location, final Object root, final PropertyConduit conduit, final String expression, final String toString)
042    {
043        super(location);
044
045        this.root = root;
046        this.conduit = conduit;
047        this.expression = expression;
048        this.toString = toString;
049
050        invariant = conduit.getAnnotation(Invariant.class) != null;
051    }
052
053    /**
054     * The default implementation of get() will throw a TapestryException (binding is write only). The fabricated
055     * subclass <em>may</em> override this method (as well as set()).
056     */
057    public Object get()
058    {
059        try
060        {
061            return conduit.get(root);
062        }
063        catch (Exception ex)
064        {
065            throw new TapestryException(ex.getMessage(), getLocation(), ex);
066        }
067    }
068
069    @Override
070    public void set(Object value)
071    {
072        try
073        {
074            conduit.set(root, value);
075        }
076        catch (Exception ex)
077        {
078            throw new TapestryException(ex.getMessage(), getLocation(), ex);
079        }
080    }
081
082    @Override
083    public String toString()
084    {
085        return toString;
086    }
087
088    /**
089     * Almost always returns false, unless the conduit provides the {@link org.apache.tapestry5.internal.services.Invariant}
090     * annotation.
091     */
092    @Override
093    public boolean isInvariant()
094    {
095        return invariant;
096    }
097
098    @Override
099    public Class getBindingType()
100    {
101        return conduit.getPropertyType();
102    }
103
104    @Override
105    public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
106    {
107        return conduit.getAnnotation(annotationClass);
108    }
109
110    public String getPropertyName() 
111    {
112        return TapestryInternalUtils.toInternalPropertyConduit(conduit).getPropertyName();
113    }
114
115    public String getExpression()
116    {
117        return expression;
118    }
119    
120}