package org.openmhealth.shim.common.mapper;


import org.openmhealth.schema.domain.omh.DataPoint;
import org.openmhealth.schema.domain.omh.SchemaId;
import org.openmhealth.schema.domain.omh.SchemaSupport;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.util.List;


/**
 * A mapper that creates data points from one or more inputs.
 *
 * @param <B> the body type of the data points to create
 * @param <I> the input type
 * @author Emerson Farrugia
 */
public interface DataPointMapper<B extends SchemaSupport, I> {

    /**
     * Maps one or more inputs into one or more data points. The parameter cardinality allows a mapper to use different
     * inputs to assemble a data point, e.g. combining a user profile API response and a blood pressure API response to
     * build an identified blood pressure data point.
     *
     * @param inputs the list of inputs
     * @return the list of data points mapped from those inputs
     */
    List<DataPoint<B>> asDataPoints(List<I> inputs);

    /**
     * Gets the schema identifier of the data point body that this mapper creates. This default implementation assumes
     * that body classes have a default constructor used for serialization, and must be overridden if they don't.
     *
     * @return the schema identifier of the body type
     */
    @SuppressWarnings("unchecked")
    default SchemaId getBodySchemaId() {

        try {
            Class<B> bodyClass = (Class<B>)
                    ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

            Constructor<B> bodyClassConstructor = bodyClass.getDeclaredConstructor();
            bodyClassConstructor.setAccessible(true);

            return bodyClassConstructor.newInstance().getSchemaId();
        }
        catch (NoSuchMethodException | InstantiationException | InvocationTargetException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}

@@ -357,16 +357,68 @@
 .List;%0A%0A
+import static java.util.Collections.singletonList;%0A%0A
 %0A/**%0A * 
@@ -1132,24 +1132,186 @@
 %3E inputs);%0A%0A
+    /**%0A     * @see #asDataPoints(List)%0A     */%0A    default List%3CDataPoint%3CB%3E%3E asDataPoints(I input) %7B%0A%0A        return asDataPoints(singletonList(input));%0A    %7D%0A%0A
     /**%0A    

Add a single response convenience method to data point mappers