    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}