001    /*
002     * (c) 2003-2005, 2009, 2010 ThoughtWorks Ltd
003     * All rights reserved.
004     *
005     * The software in this package is published under the terms of the BSD
006     * style license a copy of which has been included with this distribution in
007     * the LICENSE.txt file.
008     * 
009     * Created on 04-Feb-2004
010     */
011    package com.thoughtworks.proxy.toys.echo;
012    
013    import java.io.PrintWriter;
014    
015    import com.thoughtworks.proxy.ProxyFactory;
016    import com.thoughtworks.proxy.factory.StandardProxyFactory;
017    import com.thoughtworks.proxy.toys.decorate.Decorating;
018    
019    /**
020     * Factory for echoing proxy instances.
021     * <p>
022     * The Echoing toy acts as a decorator where every method invocation is written to a PrintWriter first.
023     * </p>
024     *
025     * @author Dan North
026     * @author J&ouml;rg Schaible
027     * @author Juan Li
028     * @author Paul Hammant
029     * @see com.thoughtworks.proxy.toys.echo
030     * @since 0.1
031     */
032    public class Echoing<T> {
033    
034        private Class<T> type;
035        private Object delegate;
036        private PrintWriter printWriter = new PrintWriter(System.err);
037    
038        private Echoing(final Class<T> type) {
039            this.type = type;
040        }
041    
042        /**
043         * Creates a factory for proxy instances that allow delegation.
044         *
045         * @param type the type of the proxy when it is finally created.
046         * @return a factory that will proxy instances of the supplied type.
047         * @since 1.0
048         */
049        public static <T> EchoingWithOrTo<T> proxy(final Class<T> type) {
050            return new EchoingWithOrTo<T>(new Echoing<T>(type));
051        }
052    
053        public static class EchoingWithOrTo<T> extends EchoingTo<T> {
054    
055            private EchoingWithOrTo(Echoing<T> echoing) {
056                super(echoing);
057            }
058    
059            /**
060             * Specify the delegate.
061             *
062             * @param delegate the object the proxy delegates to.
063             * @return the factory that will proxy instances of the supplied type.
064             * @since 1.0
065             */
066            public EchoingTo<T> with(final Object delegate) {
067                echoing.delegate = delegate;
068                return new EchoingTo<T>(echoing);
069            }
070    
071        }
072    
073        public static class EchoingTo<T> {
074            protected Echoing<T> echoing;
075    
076            private EchoingTo(Echoing<T> echoing) {
077                this.echoing = echoing;
078            }
079    
080            /**
081             * Specify the printWriter.
082             *
083             * @param printWriter which receives the output
084             * @return the factory that will proxy instances of the supplied type.
085             * @since 1.0
086             */
087            public EchoingBuild<T> to(final PrintWriter printWriter) {
088                echoing.printWriter = printWriter;
089                return new EchoingBuild<T>(echoing);
090            }
091    
092        }
093    
094        public static class EchoingBuild<T> {
095            private Echoing<T> echoing;
096    
097            private EchoingBuild(Echoing<T> echoing) {
098                this.echoing = echoing;
099            }
100    
101    
102            /**
103             * Creating a delegating proxy for an object using the {@link StandardProxyFactory}.
104             *
105             * @return the created proxy implementing the <tt>type</tt>
106             * @since 1.0
107             */
108            public T build() {
109                return build(new StandardProxyFactory());
110            }
111    
112            /**
113             * Creating a delegating proxy for an object using a special {@link ProxyFactory}.
114             *
115             * @param proxyFactory the {@link ProxyFactory} to use.
116             * @return the created proxy implementing the <tt>type</tt>
117             * @since 1.0
118             */
119            public T build(final ProxyFactory proxyFactory) {
120                EchoDecorator<T> decorator = new EchoDecorator<T>(echoing.printWriter, proxyFactory);
121                return Decorating.proxy(echoing.delegate, echoing.type).visiting(decorator).build(proxyFactory);
122            }
123        }
124    }