package mil.nga.giat.mage.sdk.jackson.deserializer; import android.util.Log; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.text.DateFormat; import java.text.ParseException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; import mil.nga.giat.mage.sdk.datastore.observation.Attachment; import mil.nga.giat.mage.sdk.datastore.observation.Observation; import mil.nga.giat.mage.sdk.datastore.observation.ObservationFavorite; import mil.nga.giat.mage.sdk.datastore.observation.ObservationImportant; import mil.nga.giat.mage.sdk.datastore.observation.ObservationProperty; import mil.nga.giat.mage.sdk.datastore.observation.State; import mil.nga.giat.mage.sdk.datastore.user.Event; import mil.nga.giat.mage.sdk.utils.ISO8601DateFormatFactory; public class ObservationDeserializer extends Deserializer { private static final String LOG_NAME = ObservationDeserializer.class.getName(); private GeometryDeserializer geometryDeserializer = new GeometryDeserializer(); private AttachmentDeserializer attachmentDeserializer = new AttachmentDeserializer(); private DateFormat iso8601Format = ISO8601DateFormatFactory.ISO8601(); private Event event = null; public ObservationDeserializer(Event event) { this.event = event; } public List<Observation> parseObservations(InputStream is) throws JsonParseException, IOException { List<Observation> observations = new ArrayList<>(); JsonParser parser = factory.createParser(is); if (parser.nextToken() != JsonToken.START_ARRAY) { return observations; } while (parser.nextToken() != JsonToken.END_ARRAY) { observations.add(parseObservation(parser)); } parser.close(); return observations; } public Observation parseObservation(InputStream is) throws JsonParseException, IOException { JsonParser parser = factory.createParser(is); parser.nextToken(); Observation observation = parseObservation(parser); parser.close(); return observation; } private Observation parseObservation(JsonParser parser) throws JsonParseException, IOException { Observation observation = new Observation(); observation.setEvent(event); if (parser.getCurrentToken() != JsonToken.START_OBJECT) return observation; while (parser.nextToken() != JsonToken.END_OBJECT) { String name = parser.getCurrentName(); if ("id".equals(name)) { parser.nextToken(); observation.setDirty(false); observation.setRemoteId(parser.getText()); } else if ("userId".equals(name)) { parser.nextToken(); observation.setUserId(parser.getText()); } else if ("deviceId".equals(name)) { parser.nextToken(); observation.setDeviceId(parser.getText()); } else if ("lastModified".equals(name)) { parser.nextToken(); try { Date d = iso8601Format.parse(parser.getText()); observation.setLastModified(d); } catch (ParseException e) { Log.e(LOG_NAME, "Problem paring date."); } } else if ("url".equals(name)) { parser.nextToken(); observation.setUrl(parser.getText()); } else if ("state".equals(name)) { parser.nextToken(); observation.setState(parseState(parser)); } else if ("geometry".equals(name)) { parser.nextToken(); observation.setGeometry(geometryDeserializer.parseGeometry(parser)); } else if ("properties".equals(name)) { parser.nextToken(); observation.setProperties(parseProperties(parser)); } else if ("attachments".equals(name)) { parser.nextToken(); observation.setAttachments(parseAttachments(parser)); } else if ("important".equals(name)) { parser.nextToken(); observation.setImportant(parseImportant(parser)); } else if ("favoriteUserIds".equals(name)) { parser.nextToken(); observation.setFavorites(parseFavoriteUsers(parser)); } else { parser.nextToken(); parser.skipChildren(); } } Map<String, ObservationProperty> properties = observation.getPropertiesMap(); // timestamp is special pull it out of properties and set it at the top // level ObservationProperty timestamp = properties.get("timestamp"); if (timestamp != null) { try { Date d = iso8601Format.parse(timestamp.getValue().toString()); observation.setTimestamp(d); } catch (ParseException pe) { Log.w(LOG_NAME, "Unable to parse date: " + timestamp + " for location: " + observation.getRemoteId(), pe); } } return observation; } private State parseState(JsonParser parser) throws JsonParseException, IOException { State state = State.ACTIVE; if (parser.getCurrentToken() != JsonToken.START_OBJECT) return state; while (parser.nextToken() != JsonToken.END_OBJECT) { String name = parser.getCurrentName(); if ("name".equals(name)) { parser.nextToken(); String stateString = parser.getText(); if (stateString != null) { try { state = State.valueOf(stateString.trim().toUpperCase()); } catch (Exception e) { Log.e(LOG_NAME, "Could not parse state: " + String.valueOf(stateString)); } } } else { parser.nextToken(); parser.skipChildren(); } } return state; } private Collection<ObservationProperty> parseProperties(JsonParser parser) throws JsonParseException, IOException { Collection<ObservationProperty> properties = new ArrayList<>(); while (parser.nextToken() != JsonToken.END_OBJECT) { String key = parser.getCurrentName(); JsonToken token = parser.nextToken(); if (token == JsonToken.START_OBJECT) { parser.skipChildren(); } else if (token == JsonToken.START_ARRAY) { ArrayList<String> stringArrayList = new ArrayList<>(); while (parser.nextToken() != JsonToken.END_ARRAY) { String arrayValue = parser.getValueAsString(); stringArrayList.add(arrayValue); } Serializable value = stringArrayList; properties.add(new ObservationProperty(key, value)); } else if (token != JsonToken.VALUE_NULL) { Serializable value = parser.getText(); if (token.isNumeric()) { switch (parser.getNumberType()) { case BIG_DECIMAL: break; case BIG_INTEGER: break; case DOUBLE: value = parser.getDoubleValue(); break; case FLOAT: value = parser.getFloatValue(); break; case INT: value = parser.getIntValue(); break; case LONG: value = parser.getLongValue(); break; default: break; } } else if (token.isBoolean()) { value = parser.getBooleanValue(); } properties.add(new ObservationProperty(key, value)); } } return properties; } private Collection<Attachment> parseAttachments(JsonParser parser) throws IOException { Collection<Attachment> attachments = new ArrayList<>(); if (parser.getCurrentToken() != JsonToken.START_ARRAY) { return attachments; } while (parser.nextToken() != JsonToken.END_ARRAY) { attachments.add(attachmentDeserializer.parseAttachment(parser)); } return attachments; } private ObservationImportant parseImportant(JsonParser parser) throws IOException { ObservationImportant important = new ObservationImportant(); important.setImportant(true); important.setDirty(false); while (parser.nextToken() != JsonToken.END_OBJECT) { String name = parser.getCurrentName(); parser.nextToken(); if ("userId".equals(name)) { important.setUserId(parser.getText()); } else if ("timestamp".equals(name)) { String dateTimeString = parser.getText().toString(); try { Date d = iso8601Format.parse(dateTimeString); important.setTimestamp(d); } catch (ParseException pe) { Log.w(LOG_NAME, "Unable to parse date: " + dateTimeString + " for observation"); } } else if ("description".equals(name)) { important.setDescription(parser.getText()); } else { parser.skipChildren(); } } return important; } private Collection<ObservationFavorite> parseFavoriteUsers(JsonParser parser) throws IOException { Collection<ObservationFavorite> favorites = new ArrayList<>(); if (parser.getCurrentToken() != JsonToken.START_ARRAY) { return favorites; } while (parser.nextToken() != JsonToken.END_ARRAY) { String userId = parser.getValueAsString(); ObservationFavorite favorite = new ObservationFavorite(userId, true); favorite.setDirty(Boolean.FALSE); favorites.add(favorite); } return favorites; } }