// Path: src/main/java/com/feedzai/fos/impl/weka/exception/Data2ConfigurationMismatch.java
// public class Data2ConfigurationMismatch extends WekaClassifierException {
// 
//     /**
//      * Creates a new configuration with the given message.
//      *
//      * @param message the configuration problem description
//      */
//     public Data2ConfigurationMismatch(String message) {
//         super(message);
//     }
// }
// 
// Path: src/main/java/com/feedzai/fos/impl/weka/exception/WekaClassifierException.java
// public class WekaClassifierException extends FOSException {
//     /**
//      * Builds a new exception from the given throwable.
//      *
//      * @param e the underlying throwable
//      */
//     public WekaClassifierException(Throwable e) {
//         super(e);
//     }
// 
//     /**
//      * Create a new exception with the given message.
//      *
//      * @param msg the message that explains the exception
//      */
//     public WekaClassifierException(String msg) {
//         super(msg);
//     }
// 
//     /**
//      * Create a new exception with the given message and cause.
//      *
//      * @param msg the message that explains the exception
//      * @param cause the original exception that originated this one
//      */
//     public WekaClassifierException(String msg, Throwable cause) {
//         super(msg, cause);
//     }
// }
// 
// Path: src/main/java/com/feedzai/fos/impl/weka/utils/setter/InstanceSetter.java
// public interface InstanceSetter {
//     /**
//      * Sets the given <code>attribute</code> to the <code>value</code>.
//      *
//      * @param instance  the instance where to set the value
//      * @param attribute the attribute to set
//      * @param value     the value to set
//      */
//     void set(Instance instance,Attribute attribute, Object value) throws FOSException;
// }


import weka.core.Instances;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
import com.feedzai.fos.api.*;
import com.feedzai.fos.common.validation.NotNull;
import com.feedzai.fos.common.validation.Nullable;
import com.feedzai.fos.impl.weka.exception.Data2ConfigurationMismatch;
import com.feedzai.fos.impl.weka.exception.WekaClassifierException;
import com.feedzai.fos.impl.weka.utils.setter.InstanceSetter;
import weka.classifiers.Classifier;
import weka.core.FastVector;
import weka.core.Instance;

    /**
     * Converts from the received Object[] to a weka <code>Instance</code>.
     *
     * @param data       the Object[] to convert (the scorable)
     * @param setters    the setters that will copy the data to the instance
     * @param attributes the list of attributes to copy over
     * @return an <code>Instance</code> with all data elements copied over from the Object[]
     * @throws WekaClassifierException when the setters and the data do not have the same size (more data than setters, or more setters than data)
     */

    public static Instance objectArray2Instance(Object[] data, InstanceSetter[] setters, FastVector attributes) throws FOSException {
        checkNotNull(data, "Instance cannot be null");
        checkNotNull(attributes, "Attributes cannot be null");
        checkNotNull(setters, "Setters cannot be null");

        Instance instance = new Instance(attributes.size());

        if (data.length == setters.length) {
            for (int idx = 0; idx < data.length; idx++) {
                if (data[idx] != null) {
                    setters[idx].set(instance, (weka.core.Attribute) attributes.elementAt(idx), data[idx].toString());
                } else {
                    instance.setMissing(idx);
                }
            }
        } else {
            throw new Data2ConfigurationMismatch(String.format("Data is not the same size as configured attributes (expected data size '%s' but was '%s')", setters.length, data.length));
        }

// Path: src/main/java/com/feedzai/fos/impl/weka/exception/Data2ConfigurationMismatch.java
// public class Data2ConfigurationMismatch extends WekaClassifierException {
// 
//     /**
//      * Creates a new configuration with the given message.
//      *
//      * @param message the configuration problem description
//      */
//     public Data2ConfigurationMismatch(String message) {
//         super(message);
//     }
// }
// 
// Path: src/main/java/com/feedzai/fos/impl/weka/exception/WekaClassifierException.java
// public class WekaClassifierException extends FOSException {
//     /**
//      * Builds a new exception from the given throwable.
//      *
//      * @param e the underlying throwable
//      */
//     public WekaClassifierException(Throwable e) {
//         super(e);
//     }
// 
//     /**
//      * Create a new exception with the given message.
//      *
//      * @param msg the message that explains the exception
//      */
//     public WekaClassifierException(String msg) {
//         super(msg);
//     }
// 
//     /**
//      * Create a new exception with the given message and cause.
//      *
//      * @param msg the message that explains the exception
//      * @param cause the original exception that originated this one
//      */
//     public WekaClassifierException(String msg, Throwable cause) {
//         super(msg, cause);
//     }
// }
// 
// Path: src/main/java/com/feedzai/fos/impl/weka/utils/setter/InstanceSetter.java
// public interface InstanceSetter {
//     /**
//      * Sets the given <code>attribute</code> to the <code>value</code>.
//      *
//      * @param instance  the instance where to set the value
//      * @param attribute the attribute to set
//      * @param value     the value to set
//      */
//     void set(Instance instance,Attribute attribute, Object value) throws FOSException;
// }


// Path: src/main/java/com/feedzai/fos/impl/weka/utils/WekaUtils.java
import weka.core.Instances;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
import com.feedzai.fos.api.*;
import com.feedzai.fos.common.validation.NotNull;
import com.feedzai.fos.common.validation.Nullable;
import com.feedzai.fos.impl.weka.exception.Data2ConfigurationMismatch;
import com.feedzai.fos.impl.weka.exception.WekaClassifierException;
import com.feedzai.fos.impl.weka.utils.setter.InstanceSetter;
import weka.classifiers.Classifier;
import weka.core.FastVector;
import weka.core.Instance;


    /**
     * Converts from the received Object[] to a weka <code>Instance</code>.
     *
     * @param data       the Object[] to convert (the scorable)
     * @param setters    the setters that will copy the data to the instance
     * @param attributes the list of attributes to copy over
     * @return an <code>Instance</code> with all data elements copied over from the Object[]
     * @throws WekaClassifierException when the setters and the data do not have the same size (more data than setters, or more setters than data)
     */

    public static Instance objectArray2Instance(Object[] data, InstanceSetter[] setters, FastVector attributes) throws FOSException {
        checkNotNull(data, "Instance cannot be null");
        checkNotNull(attributes, "Attributes cannot be null");
        checkNotNull(setters, "Setters cannot be null");

        Instance instance = new Instance(attributes.size());

        if (data.length == setters.length) {
            for (int idx = 0; idx < data.length; idx++) {
                if (data[idx] != null) {
                    setters[idx].set(instance, (weka.core.Attribute) attributes.elementAt(idx), data[idx].toString());
                } else {
                    instance.setMissing(idx);
                }
            }
        } else {
            throw new Data2ConfigurationMismatch(String.format("Data is not the same size as configured attributes (expected data size '%s' but was '%s')", setters.length, data.length));
        }

        return instance;