// Path: contrib/grpc-contrib/src/main/java/com/salesforce/grpc/contrib/instancemode/PerCallService.java
// public class PerCallService<T extends BindableService> implements BindableService {
//     private ServerServiceDefinition perCallBinding;
// 
//     /**
//      * Create a {@code PerCallService} for a provided service implementation class, generated by a factory method.
//      *
//      * @param factory A factory that will initialize a new service implementation object for every call.
//      */
//     public PerCallService(Supplier<T> factory) {
//         perCallBinding = bindService(factory);
//     }
// 
//     /**
//      * Create a {@code PerCallService} for a provided service implementation class. The provided class must have a
//      * default constructor.
//      *
//      * @param clazz The service implementation class to decorate.
//      */
//     public PerCallService(Class<T> clazz) {
//         this (() -> {
//             try {
//                 return clazz.newInstance();
//             } catch (ReflectiveOperationException e) {
//                 throw new IllegalArgumentException("Class " + clazz.getName() + " must have a public default constructor", e);
//             }
//         });
//     }
// 
//     @SuppressWarnings("unchecked")
//     private ServerServiceDefinition bindService(Supplier<T> factory) {
//         ServerServiceDefinition baseDefinition = factory.get().bindService();
//         ServiceDescriptor descriptor = baseDefinition.getServiceDescriptor();
//         Collection<ServerMethodDefinition<?, ?>> methods =  baseDefinition.getMethods();
// 
//         ServerServiceDefinition.Builder builder = ServerServiceDefinition.builder(descriptor);
//         methods.forEach(method -> builder.addMethod(ServerMethodDefinition.create(method.getMethodDescriptor(), new PerCallServerCallHandler(factory))));
//         return builder.build();
//     }
// 
//     @Override
//     public ServerServiceDefinition bindService() {
//         return perCallBinding;
//     }
// 
//     /**
//      * Internal class implementing the per-call service pattern.
//      */
//     private class PerCallServerCallHandler implements ServerCallHandler {
//         private Supplier<T> factory;
// 
//         PerCallServerCallHandler(Supplier<T> factory) {
//             this.factory = factory;
//         }
// 
//         @Override
//         @SuppressWarnings("unchecked")
//         public ServerCall.Listener startCall(ServerCall call, Metadata headers) {
//             BindableService instance = factory.get();
//             ServerServiceDefinition definition =  instance.bindService();
//             ServerMethodDefinition method = definition.getMethod(call.getMethodDescriptor().getFullMethodName());
// 
//             return new ForwardingServerCallListener.SimpleForwardingServerCallListener<T>(method.getServerCallHandler().startCall(call, headers)) {
//                 @Override
//                 public void onCancel() {
//                     super.onCancel();
//                     close();
//                 }
// 
//                 @Override
//                 public void onComplete() {
//                     super.onComplete();
//                     close();
//                 }
// 
//                 private void close() {
//                     if (instance instanceof AutoCloseable) {
//                         try {
//                             ((AutoCloseable) instance).close();
//                         } catch (Throwable t) {
//                             throw new RuntimeException(t);
//                         }
//                     }
//                 }
//             };
//         }
//     }
// }


import com.salesforce.grpc.contrib.GreeterGrpc;
import com.salesforce.grpc.contrib.HelloRequest;
import com.salesforce.grpc.contrib.HelloResponse;
import com.salesforce.grpc.contrib.instancemode.PerCallService;
import io.grpc.stub.StreamObserver;
import io.grpc.testing.GrpcServerRule;
import org.junit.Rule;
import org.junit.Test;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
package com.salesforce.grpc.contrib.instancemode;




public class PerCallServiceTest {
    @Rule public final GrpcServerRule serverRule = new GrpcServerRule();

    @Test
    public void perCallShouldInstantiateMultipleInstances() throws Exception {
        AtomicInteger closeCount = new AtomicInteger(0);

        class TestService extends GreeterGrpc.GreeterImplBase implements AutoCloseable {
            public TestService() {}

            @Override
            public void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
                responseObserver.onNext(HelloResponse.newBuilder().setMessage(Integer.toString(System.identityHashCode(this))).build());
                responseObserver.onCompleted();
            }

            @Override
            public void close() {
                closeCount.incrementAndGet();
            }
        }

// Path: contrib/grpc-contrib/src/main/java/com/salesforce/grpc/contrib/instancemode/PerCallService.java
// public class PerCallService<T extends BindableService> implements BindableService {
//     private ServerServiceDefinition perCallBinding;
// 
//     /**
//      * Create a {@code PerCallService} for a provided service implementation class, generated by a factory method.
//      *
//      * @param factory A factory that will initialize a new service implementation object for every call.
//      */
//     public PerCallService(Supplier<T> factory) {
//         perCallBinding = bindService(factory);
//     }
// 
//     /**
//      * Create a {@code PerCallService} for a provided service implementation class. The provided class must have a
//      * default constructor.
//      *
//      * @param clazz The service implementation class to decorate.
//      */
//     public PerCallService(Class<T> clazz) {
//         this (() -> {
//             try {
//                 return clazz.newInstance();
//             } catch (ReflectiveOperationException e) {
//                 throw new IllegalArgumentException("Class " + clazz.getName() + " must have a public default constructor", e);
//             }
//         });
//     }
// 
//     @SuppressWarnings("unchecked")
//     private ServerServiceDefinition bindService(Supplier<T> factory) {
//         ServerServiceDefinition baseDefinition = factory.get().bindService();
//         ServiceDescriptor descriptor = baseDefinition.getServiceDescriptor();
//         Collection<ServerMethodDefinition<?, ?>> methods =  baseDefinition.getMethods();
// 
//         ServerServiceDefinition.Builder builder = ServerServiceDefinition.builder(descriptor);
//         methods.forEach(method -> builder.addMethod(ServerMethodDefinition.create(method.getMethodDescriptor(), new PerCallServerCallHandler(factory))));
//         return builder.build();
//     }
// 
//     @Override
//     public ServerServiceDefinition bindService() {
//         return perCallBinding;
//     }
// 
//     /**
//      * Internal class implementing the per-call service pattern.
//      */
//     private class PerCallServerCallHandler implements ServerCallHandler {
//         private Supplier<T> factory;
// 
//         PerCallServerCallHandler(Supplier<T> factory) {
//             this.factory = factory;
//         }
// 
//         @Override
//         @SuppressWarnings("unchecked")
//         public ServerCall.Listener startCall(ServerCall call, Metadata headers) {
//             BindableService instance = factory.get();
//             ServerServiceDefinition definition =  instance.bindService();
//             ServerMethodDefinition method = definition.getMethod(call.getMethodDescriptor().getFullMethodName());
// 
//             return new ForwardingServerCallListener.SimpleForwardingServerCallListener<T>(method.getServerCallHandler().startCall(call, headers)) {
//                 @Override
//                 public void onCancel() {
//                     super.onCancel();
//                     close();
//                 }
// 
//                 @Override
//                 public void onComplete() {
//                     super.onComplete();
//                     close();
//                 }
// 
//                 private void close() {
//                     if (instance instanceof AutoCloseable) {
//                         try {
//                             ((AutoCloseable) instance).close();
//                         } catch (Throwable t) {
//                             throw new RuntimeException(t);
//                         }
//                     }
//                 }
//             };
//         }
//     }
// }


// Path: contrib/grpc-contrib/src/test/java/com/salesforce/grpc/contrib/instancemode/PerCallServiceTest.java
import com.salesforce.grpc.contrib.GreeterGrpc;
import com.salesforce.grpc.contrib.HelloRequest;
import com.salesforce.grpc.contrib.HelloResponse;
import com.salesforce.grpc.contrib.instancemode.PerCallService;
import io.grpc.stub.StreamObserver;
import io.grpc.testing.GrpcServerRule;
import org.junit.Rule;
import org.junit.Test;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

package com.salesforce.grpc.contrib.instancemode;




public class PerCallServiceTest {
    @Rule public final GrpcServerRule serverRule = new GrpcServerRule();

    @Test
    public void perCallShouldInstantiateMultipleInstances() throws Exception {
        AtomicInteger closeCount = new AtomicInteger(0);

        class TestService extends GreeterGrpc.GreeterImplBase implements AutoCloseable {
            public TestService() {}

            @Override
            public void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
                responseObserver.onNext(HelloResponse.newBuilder().setMessage(Integer.toString(System.identityHashCode(this))).build());
                responseObserver.onCompleted();
            }

            @Override
            public void close() {
                closeCount.incrementAndGet();
            }
        }

        serverRule.getServiceRegistry().addService(new PerCallService<TestService>(() -> new TestService()));