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    
015    package org.apache.tapestry5.internal.bindings;
016    
017    import org.apache.tapestry5.PropertyConduit;
018    import org.apache.tapestry5.internal.TapestryInternalUtils;
019    import org.apache.tapestry5.internal.services.Invariant;
020    import org.apache.tapestry5.ioc.Location;
021    import org.apache.tapestry5.ioc.internal.util.TapestryException;
022    
023    import 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     */
029    public 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    }