// Path: fos-common/src/main/java/com/feedzai/fos/common/kryo/CustomUUIDSerializer.java
// public class CustomUUIDSerializer extends Serializer<UUID> {
// 
//     @Override
//     public void write(Kryo kryo, Output output, UUID uuid) {
//         output.writeLong(uuid.getMostSignificantBits(), false);
//         output.writeLong(uuid.getLeastSignificantBits(), false);
//     }
// 
//     @Override
//     public UUID read(Kryo kryo, Input input, Class<UUID> uuidClass) {
//         return new UUID(input.readLong(false),
//                         input.readLong(false));
//     }
// }
// 
// Path: fos-common/src/main/java/com/feedzai/fos/common/kryo/ScoringRequestEnvelope.java
// public class ScoringRequestEnvelope {
//     /**
//      * List of classifier uuid to score
//      */
//     List<UUID> uuids;
// 
//     /**
//      * Instance to score
//      */
//     Object[] instance;
// 
//     /**
//      * Empty constructor to allow kryo to create new instances
//      */
//     public ScoringRequestEnvelope() {
//     }
// 
//     /**
//      * Sets the list of UUIDs to score
//      * @param uuids list of uuids to score
//      */
//     public void setUuids(List<UUID> uuids) {
//         this.uuids = uuids;
//     }
// 
//     /**
//      * Sets the instance to score
//      * @param instance instance to score
//      */
//     public void setInstance(Object[] instance) {
//         this.instance = instance;
//     }
// 
//     /**
//      * Creates a new scoring envelope
//      *
//      * @param uuids   List of classifier uuid to score
//      * @param instance instance to score
//      */
//     public ScoringRequestEnvelope(List<UUID> uuids,
//                                   Object[] instance) {
//         this.uuids = uuids;
//         this.instance = instance;
//     }
// 
//     /**
//      * Returns the list of UUID to score
//      * @return list of UUID to score
//      */
//     public List<UUID> getUUIDs() {
//         return uuids;
//     }
// 
//     /**
//      * Returns the instance to score
//      * @return the instance to score
//      */
//     public Object[] getInstance() {
//         return instance;
//     }
// }


import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.*;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.serializers.CollectionSerializer;
import com.feedzai.fos.common.kryo.CustomUUIDSerializer;
import com.feedzai.fos.common.kryo.ScoringRequestEnvelope;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
    public KryoScoringEndpoint(Socket client, Scorer scorer) throws IOException {
        this.client = client;
        this.scorer = scorer;
    }

    @Override
    public void run() {
        Kryo kryo = new Kryo();
        kryo.addDefaultSerializer(UUID.class, new CustomUUIDSerializer());
        // workaround for java.util.Arrays$ArrayList missing default constructor
        kryo.register(Arrays.asList().getClass(), new CollectionSerializer() {
            protected Collection create(Kryo kryo, Input input, Class<Collection> type) {
                return new ArrayList();
            }
        });

        Input input = new Input(BUFFER_SIZE);
        Output output = new Output(BUFFER_SIZE);

        ScoringRequestEnvelope request = null;
        try (InputStream is = client.getInputStream();
             OutputStream os = client.getOutputStream()) {
            input.setInputStream(is);
            output.setOutputStream(os);
            while (running) {
                request = kryo.readObject(input, ScoringRequestEnvelope.class);
                List<double[]> scores = scorer.score(request.getUUIDs(),
                        request.getInstance());
                kryo.writeObject(output, scores);
                output.flush();
// Path: fos-common/src/main/java/com/feedzai/fos/common/kryo/CustomUUIDSerializer.java
// public class CustomUUIDSerializer extends Serializer<UUID> {
// 
//     @Override
//     public void write(Kryo kryo, Output output, UUID uuid) {
//         output.writeLong(uuid.getMostSignificantBits(), false);
//         output.writeLong(uuid.getLeastSignificantBits(), false);
//     }
// 
//     @Override
//     public UUID read(Kryo kryo, Input input, Class<UUID> uuidClass) {
//         return new UUID(input.readLong(false),
//                         input.readLong(false));
//     }
// }
// 
// Path: fos-common/src/main/java/com/feedzai/fos/common/kryo/ScoringRequestEnvelope.java
// public class ScoringRequestEnvelope {
//     /**
//      * List of classifier uuid to score
//      */
//     List<UUID> uuids;
// 
//     /**
//      * Instance to score
//      */
//     Object[] instance;
// 
//     /**
//      * Empty constructor to allow kryo to create new instances
//      */
//     public ScoringRequestEnvelope() {
//     }
// 
//     /**
//      * Sets the list of UUIDs to score
//      * @param uuids list of uuids to score
//      */
//     public void setUuids(List<UUID> uuids) {
//         this.uuids = uuids;
//     }
// 
//     /**
//      * Sets the instance to score
//      * @param instance instance to score
//      */
//     public void setInstance(Object[] instance) {
//         this.instance = instance;
//     }
// 
//     /**
//      * Creates a new scoring envelope
//      *
//      * @param uuids   List of classifier uuid to score
//      * @param instance instance to score
//      */
//     public ScoringRequestEnvelope(List<UUID> uuids,
//                                   Object[] instance) {
//         this.uuids = uuids;
//         this.instance = instance;
//     }
// 
//     /**
//      * Returns the list of UUID to score
//      * @return list of UUID to score
//      */
//     public List<UUID> getUUIDs() {
//         return uuids;
//     }
// 
//     /**
//      * Returns the instance to score
//      * @return the instance to score
//      */
//     public Object[] getInstance() {
//         return instance;
//     }
// }


// Path: fos-api/src/main/java/com/feedzai/fos/api/KryoScoringEndpoint.java
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.*;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.serializers.CollectionSerializer;
import com.feedzai.fos.common.kryo.CustomUUIDSerializer;
import com.feedzai.fos.common.kryo.ScoringRequestEnvelope;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;

    public KryoScoringEndpoint(Socket client, Scorer scorer) throws IOException {
        this.client = client;
        this.scorer = scorer;
    }

    @Override
    public void run() {
        Kryo kryo = new Kryo();
        kryo.addDefaultSerializer(UUID.class, new CustomUUIDSerializer());
        // workaround for java.util.Arrays$ArrayList missing default constructor
        kryo.register(Arrays.asList().getClass(), new CollectionSerializer() {
            protected Collection create(Kryo kryo, Input input, Class<Collection> type) {
                return new ArrayList();
            }
        });

        Input input = new Input(BUFFER_SIZE);
        Output output = new Output(BUFFER_SIZE);

        ScoringRequestEnvelope request = null;
        try (InputStream is = client.getInputStream();
             OutputStream os = client.getOutputStream()) {
            input.setInputStream(is);
            output.setOutputStream(os);
            while (running) {
                request = kryo.readObject(input, ScoringRequestEnvelope.class);
                List<double[]> scores = scorer.score(request.getUUIDs(),
                        request.getInstance());
                kryo.writeObject(output, scores);
                output.flush();
                os.flush();