001package net.gdface.thrift;
002
003import com.google.common.base.Function;
004import net.gdface.utils.BaseTypeTransformer;
005
006import static com.google.common.base.Preconditions.*;
007import static net.gdface.thrift.ThriftUtils.*;
008/**
009 * 类型转换工具类
010 * @author guyadong
011 *
012 */
013public class TypeTransformer extends BaseTypeTransformer{
014        private static TypeTransformer instance = new TypeTransformer();
015        public static TypeTransformer getInstance() {
016                return instance;
017        }
018        public static synchronized void setInstance(TypeTransformer instance) {
019                TypeTransformer.instance = checkNotNull(instance,"instance is null");
020        }
021        protected TypeTransformer() {
022        }
023        @SuppressWarnings({ "unchecked", "rawtypes" })
024        @Override
025        public <L,R>Function<L,R> getTransformer(Class<L>left,Class<R>right){
026                Function<L, R> result = super.getTransformer(left,right);       
027                if (null == result) {
028                        if(isThriftStruct(left) && isThriftStruct(right)){
029                                // 添加 ThriftStuct对象之间的转换
030                                synchronized (this.transTable) {
031                                        // double checking
032                                        if (null == (result = (Function<L, R>) this.transTable.get(left, right))) {
033                                                if(isThriftException(left,right)){
034                                                        result = new ThriftExceptionTransformer(left,right);
035                                                }else{
036                                                        result = new ThriftStructTransformer(left,right);
037                                                }
038                                                setTransformer(left, right, result);
039                                        }
040                                }
041                        }else if(isThriftDecoratorPair(left,right) ){
042                                // 添加thrift decorator对象和被装饰对象之间的转换      
043                                updateThriftDecoatorTransformer(right,(Class<? extends ThriftDecorator>)left);
044                                result = (Function<L, R>) this.transTable.get(left, right);
045                        }else if(isThriftDecoratorPair(right,left) ){
046                                // 添加thrift decorator对象和被装饰对象之间的转换      
047                                updateThriftDecoatorTransformer(left,(Class<? extends ThriftDecorator>)right);
048                                result = (Function<L, R>) this.transTable.get(left, right);
049                        }else if(isThriftClientPair(left,right)){
050                                // 添加原始对象和thrift decorator对象之间的转换       
051                                updateThriftClientTypeTransformer(left,right);
052                                result = (Function<L, R>) this.transTable.get(left, right);
053                        }else if(isThriftClientPair(right,left)){
054                                // 添加原始对象和thrift decorator对象之间的转换       
055                                updateThriftClientTypeTransformer(right,left);
056                                result = (Function<L, R>) this.transTable.get(left, right);
057                        }
058                }
059                return result;
060        }
061        private <L,R extends ThriftDecorator<L>>void updateThriftDecoatorTransformer(Class<L>left,Class<R>right){
062                synchronized (this.transTable) {
063                        // double checking
064                        if (null == this.transTable.get(left, right)) {
065                                ThriftDecoratorTransformer<L,R> trans = new ThriftDecoratorTransformer<L,R>(left,right);
066                                setTransformer(left, right, trans.toDecoratorFun);
067                                setTransformer(right,left, trans.toDelegateFun);
068                        }
069                }
070        }
071        private <L,M extends ThriftDecorator<L>,R>void updateThriftClientTypeTransformer(Class<L>left,Class<R>right){
072                synchronized (this.transTable) {
073                        // double checking
074                        if (null == this.transTable.get(left, right)) {
075                                ThriftClientTypeTransformer<L, M, R> trans = new ThriftClientTypeTransformer<L,M,R>(left,right);
076                                setTransformer(left, right, trans.toThriftClientTypeFun);
077                                setTransformer(right,left, trans.toOriginalTypeFun);
078                        }
079                }
080        }
081        /**
082         * 将{@code value}转换为{@code right}指定的类型
083         * @param value
084         * @param left {@code value}的原类型
085         * @param right 目标类型
086         * @return
087         */
088    /**
089     * 原始类型和thrift client 类型之间的转换器,需要2将完成转换,如果{@code L->M->R}
090     * @author guyadong
091     *
092     * @param <L> 原始类型
093     * @param <M>中间类型deorator
094     * @param <R> thrift client 类型
095     */
096    public class ThriftClientTypeTransformer<L,M extends ThriftDecorator<L>,R>  {
097                private final Function<L, M> left2Middle;
098                private final Function<M, R> middle2Right;
099                private final Function<M, L> middle2Left;
100                private final Function<R, M> right2Middle;
101        public ThriftClientTypeTransformer(Class<L> left, Class<R> right) {
102                checkArgument(null != left && null != right,"left,middle,right must not be null");
103                Class<M> middClass = getMiddleClassChecked(left,right);
104                left2Middle = getTransformerChecked(left,middClass);
105                middle2Right = getTransformerChecked(middClass,right);
106                middle2Left = getTransformerChecked(middClass,left);
107                right2Middle = getTransformerChecked(right,middClass);
108        }
109        public final Function<L,R> toThriftClientTypeFun = new Function<L,R>(){
110                        @Override
111                        public R apply(L input) {
112                                M m = left2Middle.apply(input);
113                                return middle2Right.apply(m);
114                        }};
115        public final Function<R,L> toOriginalTypeFun = new Function<R,L>(){
116                        @Override
117                        public L apply(R input) {
118                                M m = right2Middle.apply(input);
119                                return middle2Left.apply(m);
120                        }};
121    }
122}