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.41.2)",
    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 static abstract class TestDeprecatedServiceImplBase implements io.grpc.BindableService {

    /**
     * <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.ServerCalls.asyncUnimplementedUnaryCall(getDeprecatedMethodMethod(), responseObserver);
    }

    @java.lang.Override public final io.grpc.ServerServiceDefinition bindService() {
      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>(
                  this, METHODID_DEPRECATED_METHOD)))
          .build();
    }
  }

  /**
   * <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);
    }
  }

  /**
   * <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);
    }
  }

  /**
   * <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 TestDeprecatedServiceImplBase serviceImpl;
    private final int methodId;

    MethodHandlers(TestDeprecatedServiceImplBase 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();
      }
    }
  }

  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;
  }
}
