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}