org.openmhealth.shim.ihealth.mapper.IHealthBodyWeightDataPointMapper.java Source code

Java tutorial

Introduction

Here is the source code for org.openmhealth.shim.ihealth.mapper.IHealthBodyWeightDataPointMapper.java

Source

/*
 * Copyright 2015 Open mHealth
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.openmhealth.shim.ihealth.mapper;

import com.fasterxml.jackson.databind.JsonNode;
import org.openmhealth.schema.domain.omh.*;

import java.util.Optional;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.openmhealth.shim.common.mapper.JsonNodeMappingSupport.asRequiredDouble;

/**
 * A mapper that translates responses from the iHealth <code>/weight.json</code> endpoint into {@link BodyWeight}
 * measures.
 *
 * @author Chris Schaefbauer
 * @author Emerson Farrugia
 * @see <a href="http://developer.ihealthlabs.com/dev_documentation_RequestfordataofWeight.htm">endpoint
 * documentation</a>
 */
public class IHealthBodyWeightDataPointMapper extends IHealthDataPointMapper<BodyWeight> {

    // Reference for conversion: https://en.wikipedia.org/wiki/Stone_(unit)
    private static final double STONE_TO_KG_FACTOR = 6.3503;

    @Override
    protected String getListNodeName() {
        return "WeightDataList";
    }

    @Override
    protected Optional<String> getMeasureUnitNodeName() {
        return Optional.of("WeightUnit");
    }

    @Override
    protected Optional<DataPoint<BodyWeight>> asDataPoint(JsonNode listEntryNode, Integer measureUnitMagicNumber) {

        checkNotNull(measureUnitMagicNumber);

        IHealthBodyWeightUnit bodyWeightUnitType = IHealthBodyWeightUnit.fromIntegerValue(measureUnitMagicNumber);
        MassUnit bodyWeightUnit = bodyWeightUnitType.getOmhUnit();

        double bodyWeightValue = getBodyWeightValueForUnitType(listEntryNode, bodyWeightUnitType);

        if (bodyWeightValue == 0) {

            return Optional.empty();
        }

        BodyWeight.Builder bodyWeightBuilder = new BodyWeight.Builder(
                new MassUnitValue(bodyWeightUnit, bodyWeightValue));

        getEffectiveTimeFrameAsDateTime(listEntryNode).ifPresent(bodyWeightBuilder::setEffectiveTimeFrame);

        getUserNoteIfExists(listEntryNode).ifPresent(bodyWeightBuilder::setUserNotes);

        BodyWeight bodyWeight = bodyWeightBuilder.build();

        return Optional.of(new DataPoint<>(createDataPointHeader(listEntryNode, bodyWeight), bodyWeight));
    }

    /**
     * @param listEntryNode A single entry from the response result array.
     * @param bodyWeightUnitType The unit type for the measure.
     * @return The body weight value for the list entry that is rendered in the correct unit.
     */
    protected double getBodyWeightValueForUnitType(JsonNode listEntryNode,
            IHealthBodyWeightUnit bodyWeightUnitType) {

        Double weightValueFromApi = asRequiredDouble(listEntryNode, "WeightValue");
        return getBodyWeightValueForUnitType(weightValueFromApi, bodyWeightUnitType);
    }

    /**
     * @param bodyWeightValue The body weight value that has been extracted from the list entry node.
     * @param bodyWeightUnitType The unit type for the measure.
     * @return A body weight value that is rendered in the correct unit.
     */
    protected double getBodyWeightValueForUnitType(double bodyWeightValue,
            IHealthBodyWeightUnit bodyWeightUnitType) {

        // iHealth has one unit type that is unsupported by OMH schemas, so we need to convert the value into a unit
        // system that is supported by the schemas.
        return bodyWeightValue * bodyWeightUnitType.getConversionFactorToOmh();
    }

    enum IHealthBodyWeightUnit {

        /*
        The conversion factor handles conversions from unsupported mass units (currently the 'Stone' unit) to omh
        supported units such that:
            
        ValueIntoSchema = ValueFromApi * Conversion
            
        We map STONE into KG because it is the SI unit for mass and the most widely accepted for measuring human
        body weight in a clinical/scientific context.
        */
        KG(0, MassUnit.KILOGRAM, 1), LB(1, MassUnit.POUND, 1), STONE(2, MassUnit.KILOGRAM, STONE_TO_KG_FACTOR);

        private final MassUnit omhUnit;
        private final double conversionFactorToOmh;
        private int magicNumber;

        IHealthBodyWeightUnit(int magicNumber, MassUnit omhUnit, double conversionFactor) {
            this.omhUnit = omhUnit;
            this.conversionFactorToOmh = conversionFactor;
            this.magicNumber = magicNumber;
        }

        public MassUnit getOmhUnit() {
            return omhUnit;
        }

        public double getConversionFactorToOmh() {
            return conversionFactorToOmh;
        }

        public static IHealthBodyWeightUnit fromIntegerValue(int unitValueFromApi) {

            for (IHealthBodyWeightUnit type : values()) {
                if (type.magicNumber == unitValueFromApi) {
                    return type;
                }
            }

            throw new UnsupportedOperationException();
        }

    }
}