001package net.gdface.thrift;
002
003import static com.google.common.base.Preconditions.*;
004import static net.gdface.thrift.ThriftUtils.*;
005
006import java.lang.reflect.Constructor;
007import java.util.Map;
008
009import com.facebook.swift.codec.metadata.ThriftStructMetadata;
010import com.google.common.base.Function;
011import com.google.common.base.Strings;
012import com.google.common.base.Throwables;
013
014/**
015 * 有{@link com.facebook.swift.codec.ThriftStruct}注释的异常类型之间的转换
016 * @author guyadong
017 *
018 * @param <L> thrift 生成的client异常类型
019 * @param <R> 实现 {@link ThriftDecorator}的装饰类异常类型
020 */
021public class ThriftExceptionTransformer<L extends Exception,R extends ThriftDecorator<? extends Exception>> 
022                        implements Function<L,R>{
023        private final ThriftStructMetadata leftMetadata;
024        private final ThriftStructMetadata rightMetadata;
025        public ThriftExceptionTransformer(Class<L> left, Class<R> right) {
026                checkArgument(isThriftException(left,right),"left and right must not be Exception with @ThriftStruct annotation"        );
027                this.leftMetadata= CATALOG.getThriftStructMetadata(left);
028                this.rightMetadata= CATALOG.getThriftStructMetadata(right);
029        }
030        @Override
031        public R apply(L input) {
032                if(null == input){
033                        return null;
034                }
035                try {
036                        Map<Short, TypeValue> data = ThriftUtils.getFiledValues(input,leftMetadata);
037                        String message = input.getMessage();
038                        Constructor<R> constructor = getStringConstructor();
039                        if(null == constructor || Strings.isNullOrEmpty(message)){
040                                // 默认构造方法创建实例
041                                return constructStruct(data,rightMetadata);
042                        }else{
043                                // 调用String参数的构造方法创建实例
044                                R instance = constructor.newInstance(message);
045                                return fillStructField(data,rightMetadata,instance);
046                        }
047                } catch (Exception e) {
048                        Throwables.throwIfUnchecked(e);
049                        throw new RuntimeException(e);
050                }
051        }
052        /**
053         * 获取String参数的构造方法,没有则返回{@code null}
054         * @return
055         */
056        @SuppressWarnings("unchecked")
057        private Constructor<R> getStringConstructor(){
058                return ThriftUtils.getConstructor((Class<R>)rightMetadata.getStructClass(),String.class); 
059        }
060    @Override
061        public String toString() {
062                StringBuilder builder = new StringBuilder()
063                                .append("ThriftExceptionTransformer [leftClass=")
064                                .append(leftMetadata.getStructType())
065                                .append(", rightClass=")
066                                .append(rightMetadata.getStructType())
067                                .append("]");
068                return builder.toString();
069        }
070}