package io.grpc.testing.compiler;

import static io.grpc.MethodDescriptor.generateFullMethodName;

/**
 * <pre>
 * Test service that has been deprecated and should generate with Java's &#64;Deprecated annotation
 * </pre>
 */
@javax.annotation.Generated(
    value = "by gRPC proto compiler (version 1.56.1-SNAPSHOT)",
    comments = "Source: grpc/testing/compiler/test.proto")
@io.grpc.stub.annotations.GrpcGenerated
@java.lang.Deprecated
public final class TestDeprecatedServiceGrpc {

  private TestDeprecatedServiceGrpc() {}

  public static final String SERVICE_NAME = "grpc.testing.compiler.TestDeprecatedService";

  // Static method descriptors that strictly reflect the proto.
  private static volatile io.grpc.MethodDescriptor<io.grpc.testing.compiler.Test.SimpleRequest,
      io.grpc.testing.compiler.Test.SimpleResponse> getDeprecatedMethodMethod;

  @io.grpc.stub.annotations.RpcMethod(
      fullMethodName = SERVICE_NAME + '/' + "DeprecatedMethod",
      requestType = io.grpc.testing.compiler.Test.SimpleRequest.class,
      responseType = io.grpc.testing.compiler.Test.SimpleResponse.class,
      methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
  public static io.grpc.MethodDescriptor<io.grpc.testing.compiler.Test.SimpleRequest,
      io.grpc.testing.compiler.Test.SimpleResponse> getDeprecatedMethodMethod() {
    io.grpc.MethodDescriptor<io.grpc.testing.compiler.Test.SimpleRequest, io.grpc.testing.compiler.Test.SimpleResponse> getDeprecatedMethodMethod;
    if ((getDeprecatedMethodMethod = TestDeprecatedServiceGrpc.getDeprecatedMethodMethod) == null) {
      synchronized (TestDeprecatedServiceGrpc.class) {
        if ((getDeprecatedMethodMethod = TestDeprecatedServiceGrpc.getDeprecatedMethodMethod) == null) {
          TestDeprecatedServiceGrpc.getDeprecatedMethodMethod = getDeprecatedMethodMethod =
              io.grpc.MethodDescriptor.<io.grpc.testing.compiler.Test.SimpleRequest, io.grpc.testing.compiler.Test.SimpleResponse>newBuilder()
              .setType(io.grpc.MethodDescriptor.MethodType.UNARY)
              .setFullMethodName(generateFullMethodName(SERVICE_NAME, "DeprecatedMethod"))
              .setSampledToLocalTracing(true)
              .setRequestMarshaller(io.grpc.protobuf.lite.ProtoLiteUtils.marshaller(
                  io.grpc.testing.compiler.Test.SimpleRequest.getDefaultInstance()))
              .setResponseMarshaller(io.grpc.protobuf.lite.ProtoLiteUtils.marshaller(
                  io.grpc.testing.compiler.Test.SimpleResponse.getDefaultInstance()))
              .build();
        }
      }
    }
    return getDeprecatedMethodMethod;
  }

  /**
   * Creates a new async stub that supports all call types for the service
   */
  public static TestDeprecatedServiceStub newStub(io.grpc.Channel channel) {
    io.grpc.stub.AbstractStub.StubFactory<TestDeprecatedServiceStub> factory =
      new io.grpc.stub.AbstractStub.StubFactory<TestDeprecatedServiceStub>() {
        @java.lang.Override
        public TestDeprecatedServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
          return new TestDeprecatedServiceStub(channel, callOptions);
        }
      };
    return TestDeprecatedServiceStub.newStub(factory, channel);
  }

  /**
   * Creates a new blocking-style stub that supports unary and streaming output calls on the service
   */
  public static TestDeprecatedServiceBlockingStub newBlockingStub(
      io.grpc.Channel channel) {
    io.grpc.stub.AbstractStub.StubFactory<TestDeprecatedServiceBlockingStub> factory =
      new io.grpc.stub.AbstractStub.StubFactory<TestDeprecatedServiceBlockingStub>() {
        @java.lang.Override
        public TestDeprecatedServiceBlockingStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
          return new TestDeprecatedServiceBlockingStub(channel, callOptions);
        }
      };
    return TestDeprecatedServiceBlockingStub.newStub(factory, channel);
  }

  /**
   * Creates a new ListenableFuture-style stub that supports unary calls on the service
   */
  public static TestDeprecatedServiceFutureStub newFutureStub(
      io.grpc.Channel channel) {
    io.grpc.stub.AbstractStub.StubFactory<TestDeprecatedServiceFutureStub> factory =
      new io.grpc.stub.AbstractStub.StubFactory<TestDeprecatedServiceFutureStub>() {
        @java.lang.Override
        public TestDeprecatedServiceFutureStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
          return new TestDeprecatedServiceFutureStub(channel, callOptions);
        }
      };
    return TestDeprecatedServiceFutureStub.newStub(factory, channel);
  }

  /**
   * <pre>
   * Test service that has been deprecated and should generate with Java's &#64;Deprecated annotation
   * </pre>
   */
  @java.lang.Deprecated
  public interface AsyncService {

    /**
     * <pre>
     * An RPC method that has been deprecated and should generate with Java's &#64;Deprecated annotation
     * </pre>
     */
    @java.lang.Deprecated
    default void deprecatedMethod(io.grpc.testing.compiler.Test.SimpleRequest request,
        io.grpc.stub.StreamObserver<io.grpc.testing.compiler.Test.SimpleResponse> responseObserver) {
      io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getDeprecatedMethodMethod(), responseObserver);
    }
  }

  /**
   * Base class for the server implementation of the service TestDeprecatedService.
   * <pre>
   * Test service that has been deprecated and should generate with Java's &#64;Deprecated annotation
   * </pre>
   */
  @java.lang.Deprecated
  public static abstract class TestDeprecatedServiceImplBase
      implements io.grpc.BindableService, AsyncService {

    @java.lang.Override public final io.grpc.ServerServiceDefinition bindService() {
      return TestDeprecatedServiceGrpc.bindService(this);
    }
  }

  /**
   * A stub to allow clients to do asynchronous rpc calls to service TestDeprecatedService.
   * <pre>
   * Test service that has been deprecated and should generate with Java's &#64;Deprecated annotation
   * </pre>
   */
  @java.lang.Deprecated
  public static final class TestDeprecatedServiceStub
      extends io.grpc.stub.AbstractAsyncStub<TestDeprecatedServiceStub> {
    private TestDeprecatedServiceStub(
        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
      super(channel, callOptions);
    }

    @java.lang.Override
    protected TestDeprecatedServiceStub build(
        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
      return new TestDeprecatedServiceStub(channel, callOptions);
    }

    /**
     * <pre>
     * An RPC method that has been deprecated and should generate with Java's &#64;Deprecated annotation
     * </pre>
     */
    @java.lang.Deprecated
    public void deprecatedMethod(io.grpc.testing.compiler.Test.SimpleRequest request,
        io.grpc.stub.StreamObserver<io.grpc.testing.compiler.Test.SimpleResponse> responseObserver) {
      io.grpc.stub.ClientCalls.asyncUnaryCall(
          getChannel().newCall(getDeprecatedMethodMethod(), getCallOptions()), request, responseObserver);
    }
  }

  /**
   * A stub to allow clients to do synchronous rpc calls to service TestDeprecatedService.
   * <pre>
   * Test service that has been deprecated and should generate with Java's &#64;Deprecated annotation
   * </pre>
   */
  @java.lang.Deprecated
  public static final class TestDeprecatedServiceBlockingStub
      extends io.grpc.stub.AbstractBlockingStub<TestDeprecatedServiceBlockingStub> {
    private TestDeprecatedServiceBlockingStub(
        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
      super(channel, callOptions);
    }

    @java.lang.Override
    protected TestDeprecatedServiceBlockingStub build(
        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
      return new TestDeprecatedServiceBlockingStub(channel, callOptions);
    }

    /**
     * <pre>
     * An RPC method that has been deprecated and should generate with Java's &#64;Deprecated annotation
     * </pre>
     */
    @java.lang.Deprecated
    public io.grpc.testing.compiler.Test.SimpleResponse deprecatedMethod(io.grpc.testing.compiler.Test.SimpleRequest request) {
      return io.grpc.stub.ClientCalls.blockingUnaryCall(
          getChannel(), getDeprecatedMethodMethod(), getCallOptions(), request);
    }
  }

  /**
   * A stub to allow clients to do ListenableFuture-style rpc calls to service TestDeprecatedService.
   * <pre>
   * Test service that has been deprecated and should generate with Java's &#64;Deprecated annotation
   * </pre>
   */
  @java.lang.Deprecated
  public static final class TestDeprecatedServiceFutureStub
      extends io.grpc.stub.AbstractFutureStub<TestDeprecatedServiceFutureStub> {
    private TestDeprecatedServiceFutureStub(
        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
      super(channel, callOptions);
    }

    @java.lang.Override
    protected TestDeprecatedServiceFutureStub build(
        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
      return new TestDeprecatedServiceFutureStub(channel, callOptions);
    }

    /**
     * <pre>
     * An RPC method that has been deprecated and should generate with Java's &#64;Deprecated annotation
     * </pre>
     */
    @java.lang.Deprecated
    public com.google.common.util.concurrent.ListenableFuture<io.grpc.testing.compiler.Test.SimpleResponse> deprecatedMethod(
        io.grpc.testing.compiler.Test.SimpleRequest request) {
      return io.grpc.stub.ClientCalls.futureUnaryCall(
          getChannel().newCall(getDeprecatedMethodMethod(), getCallOptions()), request);
    }
  }

  private static final int METHODID_DEPRECATED_METHOD = 0;

  private static final class MethodHandlers<Req, Resp> implements
      io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,
      io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>,
      io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>,
      io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> {
    private final AsyncService serviceImpl;
    private final int methodId;

    MethodHandlers(AsyncService serviceImpl, int methodId) {
      this.serviceImpl = serviceImpl;
      this.methodId = methodId;
    }

    @java.lang.Override
    @java.lang.SuppressWarnings("unchecked")
    public void invoke(Req request, io.grpc.stub.StreamObserver<Resp> responseObserver) {
      switch (methodId) {
        case METHODID_DEPRECATED_METHOD:
          serviceImpl.deprecatedMethod((io.grpc.testing.compiler.Test.SimpleRequest) request,
              (io.grpc.stub.StreamObserver<io.grpc.testing.compiler.Test.SimpleResponse>) responseObserver);
          break;
        default:
          throw new AssertionError();
      }
    }

    @java.lang.Override
    @java.lang.SuppressWarnings("unchecked")
    public io.grpc.stub.StreamObserver<Req> invoke(
        io.grpc.stub.StreamObserver<Resp> responseObserver) {
      switch (methodId) {
        default:
          throw new AssertionError();
      }
    }
  }

  public static final io.grpc.ServerServiceDefinition bindService(AsyncService service) {
    return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
        .addMethod(
          getDeprecatedMethodMethod(),
          io.grpc.stub.ServerCalls.asyncUnaryCall(
            new MethodHandlers<
              io.grpc.testing.compiler.Test.SimpleRequest,
              io.grpc.testing.compiler.Test.SimpleResponse>(
                service, METHODID_DEPRECATED_METHOD)))
        .build();
  }

  private static volatile io.grpc.ServiceDescriptor serviceDescriptor;

  public static io.grpc.ServiceDescriptor getServiceDescriptor() {
    io.grpc.ServiceDescriptor result = serviceDescriptor;
    if (result == null) {
      synchronized (TestDeprecatedServiceGrpc.class) {
        result = serviceDescriptor;
        if (result == null) {
          serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
              .addMethod(getDeprecatedMethodMethod())
              .build();
        }
      }
    }
    return result;
  }
}
