All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.gdface.thrift.ThriftUtils Maven / Gradle / Ivy

The newest version!
package net.gdface.thrift;

import static com.facebook.swift.codec.metadata.FieldKind.THRIFT_FIELD;
import static com.google.common.base.Preconditions.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
import java.net.URI;
import java.net.URL;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;

import org.apache.thrift.TApplicationException;
import org.apache.thrift.protocol.TProtocolException;

import com.facebook.swift.codec.ThriftField.Requiredness;
import com.facebook.swift.codec.metadata.ThriftConstructorInjection;
import com.facebook.swift.codec.metadata.ThriftFieldMetadata;
import com.facebook.swift.codec.metadata.ThriftParameterInjection;
import com.facebook.swift.codec.metadata.ThriftStructMetadata;
import com.facebook.swift.service.RuntimeTApplicationException;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;

/**
 * thrift工具
 * @author guyadong
 *
 */
public class ThriftUtils extends BaseThriftUtils{
	public static final Set> THRIFT_BUILTIN_KNOWNTYPES = 
	ImmutableSet.of(
			boolean.class,
			byte.class,
			double.class,
			short.class,
			int.class,
			long.class,
			String.class,
			ByteBuffer.class,
			void.class,
			Boolean.class,
			Byte.class,
			Short.class,
			Integer.class,
			Long.class,
			Double.class);
	public static final Map,Class> CAST_TYPES = 
		ImmutableMap.,Class>builder()
			.put(byte[].class,ByteBuffer.class)
			.put(Date.class,Long.class)
			.put(java.sql.Date.class,Long.class)
			.put(java.sql.Time.class,Long.class)
			.put(float.class,double.class)
			.put(Float.class,Double.class)
			.put(URI.class,String.class)
			.put(URL.class,String.class)
			.build();
	public static final String DECORATOR_PKG_SUFFIX="decorator";
	public static final String CLIENT_SUFFIX="client";
	public static final String DECORATOR_CLIENT_PKG_SUFFIX= DECORATOR_PKG_SUFFIX + "." + CLIENT_SUFFIX;
	public ThriftUtils() {
	}

	/**
	 * 构造{@code metadata}指定类型的实例并填充字段
	 * 参见 com.facebook.swift.codec.internal.reflection.ReflectionThriftStructCodec#constructStruct(Map)
	 * @param data
	 * @param metadata
	 * @return T instance
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static T constructStruct(Map data,ThriftStructMetadata metadata) 
		throws Exception{
		T instance;
	    {
	        ThriftConstructorInjection constructor = metadata.getConstructorInjection().get();
	        Type[] dstTypes = constructor.getConstructor().getGenericParameterTypes();
	        Type[] srcTypes = new Type[constructor.getParameters().size()];
	        Object[] parametersValues = new Object[constructor.getParameters().size()];
	        checkState(dstTypes.length == parametersValues.length);
	        for (ThriftParameterInjection parameter : constructor.getParameters()) {
	        	TypeValue value = data.get(parameter.getId());
	            parametersValues[parameter.getParameterIndex()] = value.value;
	            srcTypes[parameter.getParameterIndex()] = value.type;
	        }
	        for(int i =0;i
	 * 参见 com.facebook.swift.codec.internal.reflection.ReflectionThriftStructCodec#constructStruct(Map)
	 * @param data
	 * @param metadata
	 * @param instance
	 * @return always instance
	 * @throws Exception
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static T fillStructField(Map data,ThriftStructMetadata metadata,T instance) 
		throws Exception{
		return (T) fillStructField((Map)data,metadata,instance,TypeTransformer.getInstance(),true);
	}


	/**
	 * 根据{@code metadata}类型数据获取{@code instance}实例所有的字段值
	 * 参见 com.facebook.swift.codec.internal.reflection.ReflectionThriftStructCodec#write(Object, org.apache.thrift.protocol.TProtocol)
	 * @param instance
	 * @param metadata
	 * @return 字段值映射表
	 */
	public static Map getFieldValues(Object instance, ThriftStructMetadata metadata) {
		checkArgument(null != instance && null != metadata && metadata.getStructClass().isInstance(instance), 
				"instance,metadata must not be null");
		
		Collection fields = metadata.getFields(THRIFT_FIELD);
		Map data = new HashMap<>(fields.size());
		for (ThriftFieldMetadata field : fields) {
			try {
	            // is the field readable?
	            if (field.isWriteOnly()) {
	                continue;
	            }
				TypeValue value = getFieldValue(instance, field);
				if (value.value == null) {
					if (field.getRequiredness() == Requiredness.REQUIRED) {
						throw new TProtocolException("required field was not set");
					} else {
						continue;
					}
				}
				data.put(field.getId(), value);
			} catch (Exception e) {
				Throwables.throwIfUnchecked(e);
				throw new RuntimeException(e);
			}
		}
		return data;
	}
	/**
	 * @param instance
	 * @param metadata
	 * @return field values
	 * @deprecated name spell error, replaced by {@link #getFieldValues(Object, ThriftStructMetadata)}
	 */
	public static Map getFiledValues(Object instance, ThriftStructMetadata metadata) {
		return getFieldValues(instance,metadata);
	}

	/** 避免{@code null}抛出异常 */
	public static  T returnNull(RuntimeTApplicationException e){
	    Throwable cause = e.getCause();
	    if (cause instanceof TApplicationException  
	            && ((TApplicationException) cause).getType() == TApplicationException.MISSING_RESULT){
	        return null;
	    }
	    throw e;
	}
	/** 避免{@code null}抛出异常 
	 * @throws Throwable */
	public static  T returnNull(Throwable e) throws Throwable{
		if(e instanceof RuntimeTApplicationException){
			return returnNull((RuntimeTApplicationException)e);
		}
	    throw e;
	}
	public static void addCallback(
			final ListenableFuture future,
			final FutureCallback callback,Executor executor) {
		checkArgument(null != callback,"callback is null");
		checkArgument(null != executor,"executor is null");
		Runnable callbackListener =
				new Runnable() {
			@Override
			public void run() {
				V value;
				try {
					value = Futures.getDone(future);
				} catch (ExecutionException e) {
					try{
						// value is null
						value = returnNull(e.getCause()); 
					}catch(Throwable t){
						callback.onFailure(t);
						return;
					}                    
				} catch (Throwable e) {
					callback.onFailure(e);
					return;
				}
				callback.onSuccess(value);
			}
		};
		future.addListener(callbackListener, executor);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy