package org.wheelmap.android.model.api; import android.os.Parcelable; import com.google.auto.value.AutoValue; import com.google.gson.Gson; import com.google.gson.TypeAdapter; import com.google.gson.annotations.SerializedName; import com.google.gson.reflect.TypeToken; import org.wheelmap.android.net.ApiModule; import org.wheelmap.android.tango.mode.Mode; import java.util.Map; @AutoValue public abstract class MeasurementInfo implements Parcelable { private static final String TYPE_DOOR = "door"; private static final String TYPE_RAMP = "ramp"; private static final String TYPE_STAIR = "stair"; private static final String TYPE_TOILET = "toilet"; private MetaData metaData; @SerializedName("data_type") public abstract String type(); public abstract String description(); public abstract MeasurementInfo withDescription(String description); abstract Map<String, Object> data(); public MetaData metaData() { if (metaData != null) { return metaData; } Gson gson = ApiModule.getInstance().gson(); String json = gson.toJson(data()); switch (type()) { case TYPE_DOOR: metaData = gson.fromJson(json, DoorMetaData.class); break; case TYPE_RAMP: metaData = gson.fromJson(json, RampMetaData.class); break; case TYPE_STAIR: metaData = gson.fromJson(json, StairMetaData.class); break; case TYPE_TOILET: metaData = gson.fromJson(json, ToiletMetaData.class); break; } return metaData; } public static MeasurementInfo create(Mode mode, String description, MetaData data) { String type = ""; switch (mode) { case DOOR: type = TYPE_DOOR; if (!(data instanceof DoorMetaData)) { throw new IllegalArgumentException(); } break; case RAMP: type = TYPE_RAMP; if (!(data instanceof RampMetaData)) { throw new IllegalArgumentException(); } break; case STAIR: type = TYPE_STAIR; if (!(data instanceof StairMetaData)) { throw new IllegalArgumentException(); } break; case TOILET: type = TYPE_TOILET; if (!(data instanceof ToiletMetaData)) { throw new IllegalArgumentException(); } break; } Gson gson = ApiModule.getInstance().gson(); Map<String, Object> metaData = gson.fromJson(gson.toJson(data), new TypeToken<Map<String, Object>>(){}.getType()); return new AutoValue_MeasurementInfo(type, description, metaData); } public static TypeAdapter<MeasurementInfo> typeAdapter(Gson gson) { return new AutoValue_MeasurementInfo.GsonTypeAdapter(gson); } public static abstract class MetaData implements Parcelable {} @AutoValue public static abstract class DoorMetaData extends MetaData { public abstract double width(); public static DoorMetaData create(double width) { return new AutoValue_MeasurementInfo_DoorMetaData(width); } } @AutoValue public static abstract class StairMetaData extends MetaData { public abstract double height(); public static StairMetaData create(double height) { return new AutoValue_MeasurementInfo_StairMetaData(height); } } @AutoValue public static abstract class RampMetaData extends MetaData { public abstract double angle(); public static RampMetaData create(double angle) { return new AutoValue_MeasurementInfo_RampMetaData(angle); } } @AutoValue public static abstract class ToiletMetaData extends MetaData { public abstract double width(); public abstract double length(); public abstract double area(); public static ToiletMetaData create(double width, double length, double area) { return new AutoValue_MeasurementInfo_ToiletMetaData(width, length, area); } } }