package org.fluxtream.connectors.bodymedia; import java.util.ArrayList; import java.util.List; import java.util.TimeZone; import org.fluxtream.core.ApiData; import org.fluxtream.core.TimezoneMap; import org.fluxtream.core.connectors.ObjectType; import org.fluxtream.core.connectors.updaters.UpdateInfo; import org.fluxtream.core.domain.AbstractFacet; import org.fluxtream.core.facets.extractors.AbstractFacetExtractor; import org.fluxtream.core.services.ConnectorUpdateService; import org.fluxtream.core.services.MetadataService; import org.fluxtream.core.utils.TimeUtils; import net.sf.json.JSONArray; import net.sf.json.JSONException; import net.sf.json.JSONObject; import org.fluxtream.core.aspects.FlxLogger; import org.joda.time.DateTime; import org.joda.time.DateTimeConstants; import org.joda.time.LocalDate; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; /** * Extracts information from the apicall and creates a facet */ @Component public class BodymediaStepFacetExtractor extends AbstractFacetExtractor { //Logs various transactions FlxLogger logger = FlxLogger.getLogger(BodymediaStepFacetExtractor.class); @Qualifier("connectorUpdateServiceImpl") @Autowired ConnectorUpdateService connectorUpdateService; DateTimeFormatter form = DateTimeFormat.forPattern("yyyyMMdd'T'HHmmssZ"); DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyyMMdd"); @Qualifier("metadataServiceImpl") @Autowired MetadataService metadataService; @Override public List<AbstractFacet> extractFacets(final UpdateInfo updateInfo, final ApiData apiData, final ObjectType objectType) throws Exception { logger.info("guestId=" + apiData.updateInfo.getGuestId() + " connector=bodymedia action=extractFacets objectType=" + objectType.getName()); ArrayList<AbstractFacet> facets; String name = objectType.getName(); if(name.equals("steps")) { facets = extractStepFacets(updateInfo, apiData); } else //If the facet to be extracted wasn't a step facet { throw new RuntimeException("Step extractor called with illegal ObjectType"); } return facets; } private ArrayList<AbstractFacet> extractStepFacets(final UpdateInfo updateInfo, final ApiData apiData) { ArrayList<AbstractFacet> facets = new ArrayList<AbstractFacet>(); /* burnJson is a JSONArray that contains a seperate JSONArray and calorie counts for each day */ JSONObject bodymediaResponse = JSONObject.fromObject(apiData.json); JSONArray daysArray = bodymediaResponse.getJSONArray("days"); if(bodymediaResponse.has("lastSync")) { DateTime d = form.parseDateTime(bodymediaResponse.getJSONObject("lastSync").getString("dateTime")); // Get timezone map from UpdateInfo context TimezoneMap tzMap = (TimezoneMap)updateInfo.getContext("tzMap"); // Insert lastSync into the updateInfo context so it's accessible to the updater updateInfo.setContext("lastSync", d); for(Object o : daysArray) { if(o instanceof JSONObject) { JSONObject day = (JSONObject) o; BodymediaStepsFacet steps = new BodymediaStepsFacet(apiData.updateInfo.apiKey.getId()); super.extractCommonFacetData(steps, apiData); steps.totalSteps = day.getInt("totalSteps"); steps.date = day.getString("date"); steps.json = day.getString("hours"); steps.lastSync = d.getMillis(); DateTime date = formatter.parseDateTime(day.getString("date")); steps.date = TimeUtils.dateFormatter.print(date.getMillis()); if(tzMap!=null) { // Create a LocalDate object which just captures the date without any // timezone assumptions LocalDate ld = new LocalDate(date.getYear(),date.getMonthOfYear(),date.getDayOfMonth()); // Use tzMap to convert date into a datetime with timezone information DateTime realDateStart = tzMap.getStartOfDate(ld); // Set the start and end times for the facet. The start time is the leading midnight // of date according to BodyMedia's idea of what timezone you were in then. // Need to figure out what end should be... steps.start = realDateStart.getMillis(); int minutesLength = 1440; steps.end = steps.start + DateTimeConstants.MILLIS_PER_MINUTE * minutesLength; } else { TimeZone timeZone = metadataService.getTimeZone(apiData.updateInfo.getGuestId(), date.getMillis()); long fromMidnight = TimeUtils.fromMidnight(date.getMillis(), timeZone); long toMidnight = TimeUtils.toMidnight(date.getMillis(), timeZone); steps.start = fromMidnight; steps.end = toMidnight; } facets.add(steps); } else throw new JSONException("Days array is not a proper JSONObject"); } } return facets; } }