001// Licensed under the Apache License, Version 2.0 (the "License"); 002// you may not use this file except in compliance with the License. 003// You may obtain a copy of the License at 004// 005// http://www.apache.org/licenses/LICENSE-2.0 006// 007// Unless required by applicable law or agreed to in writing, software 008// distributed under the License is distributed on an "AS IS" BASIS, 009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 010// See the License for the specific language governing permissions and 011// limitations under the License. 012package org.apache.tapestry5.beaneditor; 013 014import org.apache.tapestry5.internal.services.BeanModelSourceImpl; 015import org.apache.tapestry5.internal.services.PropertyConduitSourceImpl; 016import org.apache.tapestry5.internal.services.StringInterner; 017import org.apache.tapestry5.internal.services.StringInternerImpl; 018import org.apache.tapestry5.ioc.AnnotationProvider; 019import org.apache.tapestry5.ioc.Configuration; 020import org.apache.tapestry5.ioc.ObjectLocator; 021import org.apache.tapestry5.ioc.internal.BasicDataTypeAnalyzers; 022import org.apache.tapestry5.ioc.internal.BasicTypeCoercions; 023import org.apache.tapestry5.ioc.internal.services.PlasticProxyFactoryImpl; 024import org.apache.tapestry5.ioc.internal.services.PropertyAccessImpl; 025import org.apache.tapestry5.ioc.internal.services.TypeCoercerImpl; 026import org.apache.tapestry5.ioc.internal.util.TapestryException; 027import org.apache.tapestry5.ioc.services.CoercionTuple; 028import org.apache.tapestry5.ioc.services.PlasticProxyFactory; 029import org.apache.tapestry5.ioc.services.PropertyAccess; 030import org.apache.tapestry5.ioc.services.TypeCoercer; 031import org.apache.tapestry5.services.BeanModelSource; 032import org.apache.tapestry5.services.DataTypeAnalyzer; 033import org.apache.tapestry5.services.PropertyConduitSource; 034import org.slf4j.LoggerFactory; 035 036import java.lang.annotation.Annotation; 037import java.util.ArrayList; 038import java.util.Collection; 039 040/** 041 * Utility class for creating {@link BeanModelSource} instances without 042 * Tapestry-IoC. Usage of Tapestry-IoC is still recommended. 043 * 044 * The setter methods can be used to customize the BeanModelSource to be created and can be 045 * (and usually are) skipped so <code>BeanModelSource beanModelSource = new BeanModelSourceBuilder().build();</code> 046 * is all you need to do. 047 */ 048public class BeanModelSourceBuilder { 049 050 private TypeCoercer typeCoercer; 051 private PropertyAccess propertyAccess; 052 private PropertyConduitSource propertyConduitSource; 053 private PlasticProxyFactory plasticProxyFactory; 054 private DataTypeAnalyzer dataTypeAnalyzer; 055 private ObjectLocator objectLocator; 056 private StringInterner stringInterner; 057 058 /** 059 * Creates and returns a {@link BeanModelSource} instance. 060 */ 061 public BeanModelSource build() 062 { 063 064 if (typeCoercer == null) 065 { 066 createTypeCoercer(); 067 } 068 069 if (propertyAccess == null) 070 { 071 propertyAccess = new PropertyAccessImpl(); 072 } 073 074 if (dataTypeAnalyzer == null) 075 { 076 dataTypeAnalyzer = BasicDataTypeAnalyzers.createDefaultDataTypeAnalyzer(); 077 } 078 079 if (stringInterner == null) 080 { 081 stringInterner = new StringInternerImpl(); 082 } 083 084 if (plasticProxyFactory == null) 085 { 086 plasticProxyFactory = new PlasticProxyFactoryImpl(getClass().getClassLoader(), LoggerFactory.getLogger(PlasticProxyFactory.class)); 087 } 088 089 if (propertyConduitSource == null) 090 { 091 propertyConduitSource = new PropertyConduitSourceImpl(propertyAccess, plasticProxyFactory, typeCoercer, stringInterner); 092 } 093 094 if (objectLocator == null) 095 { 096 objectLocator = new AutobuildOnlyObjectLocator(); 097 } 098 099 return new BeanModelSourceImpl(typeCoercer, propertyAccess, propertyConduitSource, plasticProxyFactory, dataTypeAnalyzer, objectLocator); 100 101 } 102 103 /** 104 * Sets the {@link TypeCoercer} to be used. 105 */ 106 public BeanModelSourceBuilder setTypeCoercer(TypeCoercer typeCoercer) 107 { 108 this.typeCoercer = typeCoercer; 109 return this; 110 } 111 112 /** 113 * Sets the {@link PropertyAccess} to be used. 114 */ 115 public BeanModelSourceBuilder setPropertyAccess(PropertyAccess propertyAccess) 116 { 117 this.propertyAccess = propertyAccess; 118 return this; 119 } 120 121 /** 122 * Sets the {@link PropertyConduitSource} to be used. 123 */ 124 public BeanModelSourceBuilder setPropertyConduitSource(PropertyConduitSource propertyConduitSource) 125 { 126 this.propertyConduitSource = propertyConduitSource; 127 return this; 128 } 129 130 /** 131 * Sets the {@link PlasticProxyFactory} to be used. 132 */ 133 public BeanModelSourceBuilder setPlasticProxyFactory(PlasticProxyFactory plasticProxyFactory) 134 { 135 this.plasticProxyFactory = plasticProxyFactory; 136 return this; 137 } 138 139 /** 140 * Sets the {@link DataTypeAnalyzer} to be used. 141 */ 142 public BeanModelSourceBuilder setDataTypeAnalyzer(DataTypeAnalyzer dataTypeAnalyzer) 143 { 144 this.dataTypeAnalyzer = dataTypeAnalyzer; 145 return this; 146 } 147 148 /** 149 * Sets the {@link ObjectLocator} to be used. Actually, the only method of it actually used is 150 * {@link ObjectLocator#autobuild(Class)}, for creating objects of the class described by the 151 * {@link BeanModel}. 152 */ 153 public BeanModelSourceBuilder setObjectLocator(ObjectLocator objectLocator) 154 { 155 this.objectLocator = objectLocator; 156 return this; 157 } 158 159 /** 160 * Sets the {@link StringInterner} to be used. 161 */ 162 public BeanModelSourceBuilder setStringInterner(StringInterner stringInterner) 163 { 164 this.stringInterner = stringInterner; 165 return this; 166 } 167 168 private void createTypeCoercer() 169 { 170 CoercionTupleConfiguration configuration = new CoercionTupleConfiguration(); 171 BasicTypeCoercions.provideBasicTypeCoercions(configuration); 172 typeCoercer = new TypeCoercerImpl(configuration.getTuples()); 173 } 174 175 final private static class CoercionTupleConfiguration implements Configuration<CoercionTuple> 176 { 177 178 final private Collection<CoercionTuple> tuples = new ArrayList<CoercionTuple>(); 179 180 @Override 181 public void add(CoercionTuple tuble) 182 { 183 tuples.add(tuble); 184 } 185 186 @Override 187 public void addInstance(Class<? extends CoercionTuple> clazz) 188 { 189 throw new RuntimeException("Not implemented"); 190 } 191 192 public Collection<CoercionTuple> getTuples() 193 { 194 return tuples; 195 } 196 197 } 198 199 final private static class AutobuildOnlyObjectLocator implements ObjectLocator { 200 201 @Override 202 public <T> T getService(String serviceId, Class<T> serviceInterface) 203 { 204 throw new RuntimeException("Not implemented"); 205 } 206 207 @Override 208 public <T> T getService(Class<T> serviceInterface) 209 { 210 throw new RuntimeException("Not implemented"); 211 } 212 213 @Override 214 public <T> T getService(Class<T> serviceInterface, 215 Class<? extends Annotation>... markerTypes) 216 { 217 throw new RuntimeException("Not implemented"); 218 } 219 220 @Override 221 public <T> T getObject(Class<T> objectType, AnnotationProvider annotationProvider) 222 { 223 throw new RuntimeException("Not implemented"); 224 } 225 226 @Override 227 public <T> T autobuild(Class<T> clazz) 228 { 229 try 230 { 231 return clazz.newInstance(); 232 } 233 catch (Exception e) 234 { 235 throw new TapestryException("Couldn't instantiate class " + clazz.getName(), e); 236 } 237 } 238 239 @Override 240 public <T> T autobuild(String description, Class<T> clazz) 241 { 242 return autobuild(clazz); 243 } 244 245 public <T> T proxy(Class<T> interfaceClass, Class<? extends T> implementationClass) 246 { 247 throw new RuntimeException("Not implemented"); 248 } 249 250 } 251 252}