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 */
011package com.thoughtworks.proxy.toys.echo;
012
013import java.io.PrintWriter;
014
015import com.thoughtworks.proxy.ProxyFactory;
016import com.thoughtworks.proxy.factory.StandardProxyFactory;
017import 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 */
032public 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}