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 BasicTypeCoercions.provideJSR310TypeCoercions(configuration); 173 typeCoercer = new TypeCoercerImpl(configuration.getTuples()); 174 } 175 176 final private static class CoercionTupleConfiguration implements Configuration<CoercionTuple> 177 { 178 179 final private Collection<CoercionTuple> tuples = new ArrayList<CoercionTuple>(); 180 181 @Override 182 public void add(CoercionTuple tuble) 183 { 184 tuples.add(tuble); 185 } 186 187 @Override 188 public void addInstance(Class<? extends CoercionTuple> clazz) 189 { 190 throw new RuntimeException("Not implemented"); 191 } 192 193 public Collection<CoercionTuple> getTuples() 194 { 195 return tuples; 196 } 197 198 } 199 200 final private static class AutobuildOnlyObjectLocator implements ObjectLocator { 201 202 @Override 203 public <T> T getService(String serviceId, Class<T> serviceInterface) 204 { 205 throw new RuntimeException("Not implemented"); 206 } 207 208 @Override 209 public <T> T getService(Class<T> serviceInterface) 210 { 211 throw new RuntimeException("Not implemented"); 212 } 213 214 @Override 215 public <T> T getService(Class<T> serviceInterface, 216 Class<? extends Annotation>... markerTypes) 217 { 218 throw new RuntimeException("Not implemented"); 219 } 220 221 @Override 222 public <T> T getObject(Class<T> objectType, AnnotationProvider annotationProvider) 223 { 224 throw new RuntimeException("Not implemented"); 225 } 226 227 @Override 228 public <T> T autobuild(Class<T> clazz) 229 { 230 try 231 { 232 return clazz.newInstance(); 233 } 234 catch (Exception e) 235 { 236 throw new TapestryException("Couldn't instantiate class " + clazz.getName(), e); 237 } 238 } 239 240 @Override 241 public <T> T autobuild(String description, Class<T> clazz) 242 { 243 return autobuild(clazz); 244 } 245 246 public <T> T proxy(Class<T> interfaceClass, Class<? extends T> implementationClass) 247 { 248 throw new RuntimeException("Not implemented"); 249 } 250 251 } 252 253}