// Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package org.apache.tapestry5.beaneditor; import org.apache.tapestry5.internal.services.BeanModelSourceImpl; import org.apache.tapestry5.internal.services.PropertyConduitSourceImpl; import org.apache.tapestry5.internal.services.StringInterner; import org.apache.tapestry5.internal.services.StringInternerImpl; import org.apache.tapestry5.ioc.AnnotationProvider; import org.apache.tapestry5.ioc.Configuration; import org.apache.tapestry5.ioc.ObjectLocator; import org.apache.tapestry5.ioc.internal.BasicDataTypeAnalyzers; import org.apache.tapestry5.ioc.internal.BasicTypeCoercions; import org.apache.tapestry5.ioc.internal.services.PlasticProxyFactoryImpl; import org.apache.tapestry5.ioc.internal.services.PropertyAccessImpl; import org.apache.tapestry5.ioc.internal.services.TypeCoercerImpl; import org.apache.tapestry5.ioc.internal.util.TapestryException; import org.apache.tapestry5.ioc.services.CoercionTuple; import org.apache.tapestry5.ioc.services.PlasticProxyFactory; import org.apache.tapestry5.ioc.services.PropertyAccess; import org.apache.tapestry5.ioc.services.TypeCoercer; import org.apache.tapestry5.services.BeanModelSource; import org.apache.tapestry5.services.DataTypeAnalyzer; import org.apache.tapestry5.services.PropertyConduitSource; import org.slf4j.LoggerFactory; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Collection; /** * Utility class for creating {@link BeanModelSource} instances without * Tapestry-IoC. Usage of Tapestry-IoC is still recommended. * * The setter methods can be used to customize the BeanModelSource to be created and can be * (and usually are) skipped so <code>BeanModelSource beanModelSource = new BeanModelSourceBuilder().build();</code> * is all you need to do. */ public class BeanModelSourceBuilder { private TypeCoercer typeCoercer; private PropertyAccess propertyAccess; private PropertyConduitSource propertyConduitSource; private PlasticProxyFactory plasticProxyFactory; private DataTypeAnalyzer dataTypeAnalyzer; private ObjectLocator objectLocator; private StringInterner stringInterner; /** * Creates and returns a {@link BeanModelSource} instance. */ public BeanModelSource build() { if (typeCoercer == null) { createTypeCoercer(); } if (propertyAccess == null) { propertyAccess = new PropertyAccessImpl(); } if (dataTypeAnalyzer == null) { dataTypeAnalyzer = BasicDataTypeAnalyzers.createDefaultDataTypeAnalyzer(); } if (stringInterner == null) { stringInterner = new StringInternerImpl(); } if (plasticProxyFactory == null) { plasticProxyFactory = new PlasticProxyFactoryImpl(getClass().getClassLoader(), LoggerFactory.getLogger(PlasticProxyFactory.class)); } if (propertyConduitSource == null) { propertyConduitSource = new PropertyConduitSourceImpl(propertyAccess, plasticProxyFactory, typeCoercer, stringInterner); } if (objectLocator == null) { objectLocator = new AutobuildOnlyObjectLocator(); } return new BeanModelSourceImpl(typeCoercer, propertyAccess, propertyConduitSource, plasticProxyFactory, dataTypeAnalyzer, objectLocator); } /** * Sets the {@link TypeCoercer} to be used. */ public BeanModelSourceBuilder setTypeCoercer(TypeCoercer typeCoercer) { this.typeCoercer = typeCoercer; return this; } /** * Sets the {@link PropertyAccess} to be used. */ public BeanModelSourceBuilder setPropertyAccess(PropertyAccess propertyAccess) { this.propertyAccess = propertyAccess; return this; } /** * Sets the {@link PropertyConduitSource} to be used. */ public BeanModelSourceBuilder setPropertyConduitSource(PropertyConduitSource propertyConduitSource) { this.propertyConduitSource = propertyConduitSource; return this; } /** * Sets the {@link PlasticProxyFactory} to be used. */ public BeanModelSourceBuilder setPlasticProxyFactory(PlasticProxyFactory plasticProxyFactory) { this.plasticProxyFactory = plasticProxyFactory; return this; } /** * Sets the {@link DataTypeAnalyzer} to be used. */ public BeanModelSourceBuilder setDataTypeAnalyzer(DataTypeAnalyzer dataTypeAnalyzer) { this.dataTypeAnalyzer = dataTypeAnalyzer; return this; } /** * Sets the {@link ObjectLocator} to be used. Actually, the only method of it actually used is * {@link ObjectLocator#autobuild(Class)}, for creating objects of the class described by the * {@link BeanModel}. */ public BeanModelSourceBuilder setObjectLocator(ObjectLocator objectLocator) { this.objectLocator = objectLocator; return this; } /** * Sets the {@link StringInterner} to be used. */ public BeanModelSourceBuilder setStringInterner(StringInterner stringInterner) { this.stringInterner = stringInterner; return this; } private void createTypeCoercer() { CoercionTupleConfiguration configuration = new CoercionTupleConfiguration(); BasicTypeCoercions.provideBasicTypeCoercions(configuration); typeCoercer = new TypeCoercerImpl(configuration.getTuples()); } final private static class CoercionTupleConfiguration implements Configuration<CoercionTuple> { final private Collection<CoercionTuple> tuples = new ArrayList<CoercionTuple>(); @Override public void add(CoercionTuple tuble) { tuples.add(tuble); } @Override public void addInstance(Class<? extends CoercionTuple> clazz) { throw new RuntimeException("Not implemented"); } public Collection<CoercionTuple> getTuples() { return tuples; } } final private static class AutobuildOnlyObjectLocator implements ObjectLocator { @Override public <T> T getService(String serviceId, Class<T> serviceInterface) { throw new RuntimeException("Not implemented"); } @Override public <T> T getService(Class<T> serviceInterface) { throw new RuntimeException("Not implemented"); } @Override public <T> T getService(Class<T> serviceInterface, Class<? extends Annotation>... markerTypes) { throw new RuntimeException("Not implemented"); } @Override public <T> T getObject(Class<T> objectType, AnnotationProvider annotationProvider) { throw new RuntimeException("Not implemented"); } @Override public <T> T autobuild(Class<T> clazz) { try { return clazz.newInstance(); } catch (Exception e) { throw new TapestryException("Couldn't instantiate class " + clazz.getName(), e); } } @Override public <T> T autobuild(String description, Class<T> clazz) { return autobuild(clazz); } public <T> T proxy(Class<T> interfaceClass, Class<? extends T> implementationClass) { throw new RuntimeException("Not implemented"); } } }