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.delegate;
012
013 import com.thoughtworks.proxy.ProxyFactory;
014 import com.thoughtworks.proxy.factory.StandardProxyFactory;
015 import com.thoughtworks.proxy.kit.SimpleReference;
016
017 /**
018 * Toy factory to create proxies delegating to another object.
019 * <p>
020 * Such a proxy is used to mask the methods of an object, that are not part of a public interface. Or it is used to make
021 * an object compatible, e.g. when an object implements the methods of an interface, but does not implement the
022 * interface itself.
023 * </p>
024 *
025 * @author Dan North
026 * @author Jian Li
027 * @author Paul Hammant
028 * @see com.thoughtworks.proxy.toys.delegate
029 * @since 0.1
030 */
031 public class Delegating<T> {
032
033 private Class<T> type;
034 private Object delegate;
035 private DelegationMode delegationMode = DelegationMode.SIGNATURE;
036
037 private Delegating(Class<T> type) {
038 this.type = type;
039 }
040
041 /**
042 * Creates a factory for proxy instances that allow delegation.
043 *
044 * @param type the type of the proxy when it is finally created.
045 * @return a factory that will proxy instances of the supplied type.
046 * @since 1.0
047 */
048 public static <T> DelegatingWith<T> proxy(Class<T> type) {
049 return new DelegatingWith<T>(new Delegating<T>(type));
050 }
051
052 public static class DelegatingWith<T> {
053 private Delegating<T> delegating;
054
055 private DelegatingWith(Delegating<T> delegating) {
056 this.delegating = delegating;
057 }
058
059 /**
060 * With this delegate
061 *
062 * @param delegate the object the proxy delegates to.
063 * @return the factory that will route calls to the supplied delegate.
064 * @since 1.0
065 */
066 public DelegatingModeOrBuild<T> with(Object delegate) {
067 delegating.delegate = delegate;
068 return new DelegatingModeOrBuild<T>(delegating);
069 }
070
071 }
072
073 public static class DelegatingModeOrBuild<T> extends DelegatingBuild<T>{
074
075 private DelegatingModeOrBuild(Delegating<T> delegating) {
076 super(delegating);
077 }
078
079 /**
080 * Forces a particular delegation mode to be used.
081 *
082 * @param mode refer to {@link DelegationMode#DIRECT} or
083 * {@link DelegationMode#SIGNATURE} for allowed values.
084 * @return the factory that will proxy instances of the supplied type.
085 */
086 public DelegatingBuild<T> mode(DelegationMode mode) {
087 delegating.delegationMode = mode;
088 return new DelegatingBuild<T>(delegating);
089 }
090
091 }
092
093 public static class DelegatingBuild<T> {
094 protected Delegating<T> delegating;
095
096 private DelegatingBuild(Delegating<T> delegating) {
097 this.delegating = delegating;
098 }
099
100 /**
101 * Creating a delegating proxy for an object using the {@link StandardProxyFactory}.
102 *
103 * @return the created proxy implementing the <tt>type</tt>
104 * @since 1.0
105 */
106 public T build() {
107 return build(new StandardProxyFactory());
108 }
109
110 /**
111 * Creating a delegating proxy for an object using a special {@link ProxyFactory}.
112 *
113 * @param factory the {@link ProxyFactory} to use.
114 * @return the created proxy implementing the <tt>type</tt>
115 * @since 1.0
116 */
117 public T build(ProxyFactory factory) {
118 return factory.<T>createProxy(new DelegatingInvoker<Object>(factory,
119 new SimpleReference<Object>(delegating.delegate), delegating.delegationMode), delegating.type);
120 }
121 }
122 }