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.ProtoUtils.marshaller(
                  io.grpc.testing.compiler.Test.SimpleRequest.getDefaultInstance()))
              .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
                  io.grpc.testing.compiler.Test.SimpleResponse.getDefaultInstance()))
              .setSchemaDescriptor(new TestDeprecatedServiceMethodDescriptorSupplier("DeprecatedMethod"))
              .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 abstract class TestDeprecatedServiceBaseDescriptorSupplier
      implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier {
    TestDeprecatedServiceBaseDescriptorSupplier() {}

    @java.lang.Override
    public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() {
      return io.grpc.testing.compiler.Test.getDescriptor();
    }

    @java.lang.Override
    public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() {
      return getFileDescriptor().findServiceByName("TestDeprecatedService");
    }
  }

  private static final class TestDeprecatedServiceFileDescriptorSupplier
      extends TestDeprecatedServiceBaseDescriptorSupplier {
    TestDeprecatedServiceFileDescriptorSupplier() {}
  }

  private static final class TestDeprecatedServiceMethodDescriptorSupplier
      extends TestDeprecatedServiceBaseDescriptorSupplier
      implements io.grpc.protobuf.ProtoMethodDescriptorSupplier {
    private final String methodName;

    TestDeprecatedServiceMethodDescriptorSupplier(String methodName) {
      this.methodName = methodName;
    }

    @java.lang.Override
    public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() {
      return getServiceDescriptor().findMethodByName(methodName);
    }
  }

  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)
              .setSchemaDescriptor(new TestDeprecatedServiceFileDescriptorSupplier())
              .addMethod(getDeprecatedMethodMethod())
              .build();
        }
      }
    }
    return result;
  }
}
