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