001package com.facebook.swift.codec.metadata;
002
003import static com.google.common.base.Preconditions.checkState;
004
005import java.lang.reflect.Type;
006import java.util.List;
007import java.util.logging.Logger;
008
009import javax.annotation.concurrent.Immutable;
010
011import com.facebook.swift.codec.ThriftField.Requiredness;
012import com.facebook.swift.codec.metadata.ThriftFieldMetadata;
013import com.facebook.swift.codec.metadata.ThriftInjection;
014import com.facebook.swift.codec.metadata.ThriftParameterInjection;
015import com.google.common.primitives.Primitives;
016
017/**
018 * {@link ThriftFieldMetadata}的代理类,
019 * 重载{@link #getRequiredness()}方法,根据参数类型对返回值进行修改
020 * @author guyadong
021 *
022 */
023@Immutable
024public class DecoratorThriftFieldMetadata extends ThriftFieldMetadata {
025        private static final Logger logger = Logger.getLogger(DecoratorThriftFieldMetadata.class.getName());
026    private static Boolean primitiveOptional = null;
027    private static Boolean objectOptional = null;
028    private final Type javaType;
029        public DecoratorThriftFieldMetadata(ThriftFieldMetadata input){
030        super(
031                input.getId(),
032                input.getRequiredness(),
033                input.getThriftType(),
034                input.getName(),
035                input.getType(),
036                input.getInjections(),
037                input.getConstructorInjection(),
038                input.getMethodInjection(),
039                input.getExtraction(),
040                input.getCoercion());
041                // 获取field的类型
042                List<ThriftInjection> injections = getInjections();
043                checkState(injections.size()>0,"invalid size of injections");
044                ThriftInjection injection = injections.get(0);          
045                if(injection instanceof ThriftParameterInjection){
046                        javaType = ((ThriftParameterInjection)injection).getJavaType();
047                }else if(injection instanceof ThriftFieldInjection){
048                        javaType = ((ThriftFieldInjection)injection).getField().getType();
049                }else{
050                        javaType = null;
051                        // 对于不支持的数据类型无法获取field类型,输出警告
052                        logger.warning(
053                                        String.format("UNSUPPORED TYPE %s,can't get Java Type. "
054                                                        + "(不识别的ThriftInjection实例类型,无法实现requiredness转义)",
055                                        null == injection? null : injection.getClass().getName()));
056                }
057        }
058        /** 重载方法,实现 requiredness 转义 */
059        @Override
060        public Requiredness getRequiredness() {
061                Requiredness requiredness = super.getRequiredness();
062                checkState(Requiredness.UNSPECIFIED != requiredness);
063                // 当为primitive类型时,Requiredness 为REQUIRED
064                // 当为primitive类型的Object封装类型时(Long,Integer,Boolean),Requiredness为OPTIONAL
065                if(Boolean.TRUE.equals(objectOptional) && requiredness == Requiredness.NONE){
066                        if(javaType instanceof Class<?>)
067                        {
068                                Class<?> parameterClass = (Class<?>)javaType;
069                                if(parameterClass.isPrimitive()){
070                                        requiredness = Requiredness.REQUIRED;
071                                }else {
072                                        requiredness = Requiredness.OPTIONAL;
073                                }                               
074                        }else{
075                                requiredness = Requiredness.OPTIONAL;
076                        }
077                }else   if( !Boolean.FALSE.equals(primitiveOptional)
078                                && javaType instanceof Class<?>
079                                && requiredness == Requiredness.NONE){
080                        Class<?> parameterClass = (Class<?>)javaType;
081                        if(parameterClass.isPrimitive()){
082                                requiredness = Requiredness.REQUIRED;
083                                // logger.info(String.format("%s %s", parameterClass.getSimpleName(),requiredness));
084                        }else if(Primitives.isWrapperType(parameterClass)){
085                                requiredness = Requiredness.OPTIONAL;
086                                // logger.info(String.format("%s %s", parameterClass.getSimpleName(),requiredness));
087                        }
088                }
089                return requiredness;
090        }
091    /**
092         * 设置primitiveOptional标记<br>
093         * 指定{@link #getRequiredness}方法调用时是否对primitive类型及其封装类型(Integer,Long)参数的返回值进行替换<br>
094         * 默认值:{@code true}<br>
095         * 该方法只能被调用一次
096         * @param optional
097         * @see #getRequiredness()
098         * @throws IllegalStateException 方法已经被调用
099         */
100        public static synchronized void setPrimitiveOptional(boolean optional) {
101                checkState(null == DecoratorThriftFieldMetadata.primitiveOptional,"primitiveOptional is initialized already.");
102                DecoratorThriftFieldMetadata.primitiveOptional = optional;
103        }
104    /**
105         * 设置ObjectOptional标记<br>
106         * 指定{@link #getRequiredness}方法调用时是否对Object类型参数的返回值进行替换<br>
107         * 默认值:{@code true}<br>
108         * 该方法只能被调用一次
109         * @param optional
110         * @see #getRequiredness()
111         * @throws IllegalStateException 方法已经被调用
112         */
113        public static synchronized void setObjectOptional(Boolean optional) {
114                checkState(null == DecoratorThriftFieldMetadata.objectOptional,"ObjectOptional is initialized already.");
115                DecoratorThriftFieldMetadata.objectOptional = optional;
116        }
117
118}