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    public PropBinding(final Location location, final Object root, final PropertyConduit conduit, final String toString
040    )
041    {
042        super(location);
043
044        this.root = root;
045        this.conduit = conduit;
046        this.toString = toString;
047
048        invariant = conduit.getAnnotation(Invariant.class) != null;
049    }
050
051    /**
052     * The default implementation of get() will throw a TapestryException (binding is write only). The fabricated
053     * subclass <em>may</em> override this method (as well as set()).
054     */
055    public Object get()
056    {
057        try
058        {
059            return conduit.get(root);
060        }
061        catch (Exception ex)
062        {
063            throw new TapestryException(ex.getMessage(), getLocation(), ex);
064        }
065    }
066
067    @Override
068    public void set(Object value)
069    {
070        try
071        {
072            conduit.set(root, value);
073        }
074        catch (Exception ex)
075        {
076            throw new TapestryException(ex.getMessage(), getLocation(), ex);
077        }
078    }
079
080    @Override
081    public String toString()
082    {
083        return toString;
084    }
085
086    /**
087     * Almost always returns false, unless the conduit provides the {@link org.apache.tapestry5.internal.services.Invariant}
088     * annotation.
089     */
090    @Override
091    public boolean isInvariant()
092    {
093        return invariant;
094    }
095
096    @Override
097    public Class getBindingType()
098    {
099        return conduit.getPropertyType();
100    }
101
102    @Override
103    public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
104    {
105        return conduit.getAnnotation(annotationClass);
106    }
107
108        public String getPropertyName() 
109        {
110                return TapestryInternalUtils.toInternalPropertyConduit(conduit).getPropertyName();
111        }
112}