blob: 482b42f3034f96a484fb3c205db44cb8691a4898 [file] [log] [blame]
package com.google.net.stubby;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import javax.inject.Provider;
/**
* Descriptor for a single operation, used by Channel to execute a call.
*/
@Immutable
public class MethodDescriptor<RequestT, ResponseT> {
public enum Type {
UNARY,
CLIENT_STREAMING,
SERVER_STREAMING,
DUPLEX_STREAMING,
UNKNOWN
}
private static final Function<Provider<String>,String> HEADER_SNAPSHOT =
new Function<Provider<String>, String>() {
@Override
public String apply(@Nullable Provider<String> headerProvider) {
return headerProvider == null ? null : headerProvider.get();
}
};
private final Type type;
private final String name;
private final Marshaller<RequestT> requestMarshaller;
private final Marshaller<ResponseT> responseMarshaller;
private final long timeoutMicros;
private final ImmutableMap<String, Provider<String>> headers;
public static <RequestT, ResponseT> MethodDescriptor<RequestT, ResponseT> create(
Type type, String name, long timeout, TimeUnit timeoutUnit,
Marshaller<RequestT> requestMarshaller,
Marshaller<ResponseT> responseMarshaller) {
return new MethodDescriptor<RequestT, ResponseT>(
type, name, timeoutUnit.toMicros(timeout), requestMarshaller, responseMarshaller,
ImmutableMap.<String, Provider<String>>of());
}
private MethodDescriptor(Type type, String name, long timeoutMicros,
Marshaller<RequestT> requestMarshaller,
Marshaller<ResponseT> responseMarshaller,
ImmutableMap<String, Provider<String>> headers) {
this.type = Preconditions.checkNotNull(type);
this.name = name;
Preconditions.checkArgument(timeoutMicros > 0);
this.timeoutMicros = timeoutMicros;
this.requestMarshaller = requestMarshaller;
this.responseMarshaller = responseMarshaller;
this.headers = headers;
}
/**
* The call type of the method.
*/
public Type getType() {
return type;
}
/**
* The fully qualified name of the method
*/
public String getName() {
return name;
}
/**
* Timeout for the operation in microseconds
*/
public long getTimeout() {
return timeoutMicros;
}
/**
* Return a snapshot of the headers.
*/
public Map<String, String> getHeaders() {
if (headers.isEmpty()) {
return ImmutableMap.of();
}
return ImmutableMap.copyOf(Maps.transformValues(headers, HEADER_SNAPSHOT));
}
/**
* Parse a response payload from the given {@link InputStream}
*/
public ResponseT parseResponse(InputStream input) {
return responseMarshaller.parse(input);
}
/**
* Convert a request message to an {@link InputStream}
*/
public InputStream streamRequest(RequestT requestMessage) {
return requestMarshaller.stream(requestMessage);
}
/**
* Create a new descriptor with a different timeout
*/
public MethodDescriptor<RequestT, ResponseT> withTimeout(long timeout, TimeUnit unit) {
return new MethodDescriptor<RequestT, ResponseT>(type, name, unit.toMicros(timeout),
requestMarshaller, responseMarshaller, headers);
}
/**
* Create a new descriptor with an additional bound header.
*/
public MethodDescriptor<RequestT, ResponseT> withHeader(String headerName,
Provider<String> headerValueProvider) {
return new MethodDescriptor<RequestT, ResponseT>(type, name, timeoutMicros,
requestMarshaller, responseMarshaller,
ImmutableMap.<String, Provider<String>>builder().
putAll(headers).put(headerName, headerValueProvider).build());
}
}