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