net.gdface.thrift.EnumThriftCodec Maven / Gradle / Ivy
The newest version!
package net.gdface.thrift;
import com.facebook.swift.codec.ThriftCodec;
import com.facebook.swift.codec.ThriftProtocolType;
import com.facebook.swift.codec.internal.UnknownEnumValueException;
import com.facebook.swift.codec.metadata.ThriftCatalogWithTransformer;
import com.facebook.swift.codec.metadata.ThriftEnumMetadata;
import com.facebook.swift.codec.metadata.ThriftType;
import com.gitee.l0km.aocache.annotations.AoCacheable;
import com.gitee.l0km.aocache.annotations.AoWeakCacheable;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import org.apache.thrift.protocol.TJSONProtocolXthrift;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.protocol.TProtocolSupport;
import javax.annotation.concurrent.Immutable;
/**
* 支持负值的枚举类型编解码器
* 在默认枚举类型编解码器{@link com.facebook.swift.codec.internal.EnumThriftCodec}基础上删除非负值判断
* 当为{@link TJSONProtocolXthrift}时支持自动判断字段类型(STRING/I32)反序列化。并支持序列化为STRING
*/
@Immutable
public class EnumThriftCodec> implements ThriftCodec
{
private final ThriftType type;
private final ThriftEnumMetadata enumMetadata;
@SuppressWarnings("unchecked")
public EnumThriftCodec(ThriftType type)
{
this.type = type;
enumMetadata = (ThriftEnumMetadata) type.getEnumMetadata();
}
@Override
public ThriftType getType()
{
return type;
}
@Override
public T read(TProtocol protocol)
throws Exception
{
Object enumValue;
TJSONProtocolXthrift jsonsProtocol = TProtocolSupport.fetchJSONXthrift(protocol);
if (null != jsonsProtocol) {
enumValue = jsonsProtocol.readJSONStringOrInteger();
}else {
enumValue = protocol.readI32();
}
return read(enumValue);
}
@Override
public void write(T enumConstant, TProtocol protocol)
throws Exception
{
boolean enumValueAsString = false;
TJSONProtocolXthrift jsonsProtocol = TProtocolSupport.fetchJSONXthrift(protocol);
if(null != jsonsProtocol) {
enumValueAsString = jsonsProtocol.enumValueAsString();
}
write(enumConstant,protocol,enumValueAsString);
}
private void write(T enumConstant, TProtocol protocol,boolean enumValueAsString)
throws Exception
{
Preconditions.checkNotNull(enumConstant, "enumConstant is null");
if(enumValueAsString) {
protocol.writeString(enumConstant.name());
}else {
int enumValue;
if (enumMetadata.hasExplicitThriftValue()) {
enumValue = enumMetadata.getByEnumConstant().get(enumConstant);
}
else {
enumValue = enumConstant.ordinal();
}
protocol.writeI32(enumValue);
}
}
private T read(int enumValue)
throws Exception
{
if (enumMetadata.hasExplicitThriftValue()) {
T enumConstant = enumMetadata.getByEnumValue().get(enumValue);
if (enumConstant != null) {
return enumConstant;
}
}
else {
T[] enumConstants = enumMetadata.getEnumClass().getEnumConstants();
if (enumValue < enumConstants.length) {
return enumConstants[enumValue];
}
}
// unknown, throw unknown value exception
throw new UnknownEnumValueException(
String.format(
"Enum %s does not have a value for %s",
enumMetadata.getEnumClass(),
enumValue
)
);
}
private T read(String enumName) throws Exception {
T value = enumNamesMapOf(enumMetadata.getEnumClass()).get(enumName);
if (value != null) {
return value;
}
// unknown, throw unknown value exception
throw new UnknownEnumValueException(
String.format(
"Enum %s does not have a value for %s",
enumMetadata.getEnumClass(),
enumName
)
);
}
private T read(Object value) throws Exception {
if(value instanceof Integer) {
return read((int)value);
}else {
return read((String)value);
}
}
@AoWeakCacheable
protected static > ImmutableMap enumNamesMapOf(Class enumClass) {
ImmutableMap.Builder builder= ImmutableMap.builder();
for(T e:enumClass.getEnumConstants()) {
builder.put(e.name(), e);
}
return builder.build();
}
/**
* 生成指定枚举类型的编解码器
* @param type
* @return EnumThriftCodec 实例
*/
public static > EnumThriftCodec getCodec(Class type){
ThriftType thriftType = ThriftCatalogWithTransformer.CATALOG.getThriftType(type);
return getCodec(thriftType);
}
/**
* 生成指定枚举类型的编解码器
* @param type
* @return EnumThriftCodec 实例
* @since 1.5.0
*/
@AoCacheable
public static > EnumThriftCodec getCodec(ThriftType thriftType){
return new EnumThriftCodec(thriftType);
}
/**
* 如果是枚举类型编解码器则替换为自定义的{@link EnumThriftCodec}实例以支持不带类型的标准JSON格式数据协议
* @param
* @param codec
* @since 1.5.0
*/
@SuppressWarnings("unchecked")
public static ThriftCodec usingIfEnum(ThriftCodec codec) {
if (ThriftProtocolType.ENUM.equals(codec.getType().getProtocolType()) && !(codec instanceof EnumThriftCodec)) {
return (ThriftCodec) EnumThriftCodec.getCodec(codec.getType());
}
return codec;
}
}