Java tutorial
// Copyright 2015 The Project Buendia Authors // // 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 distrib- // uted 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 // specific language governing permissions and limitations under the License. package org.projectbuendia.client.models; import android.content.ContentValues; import android.database.Cursor; import org.joda.time.DateTime; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.projectbuendia.client.net.Server; import org.projectbuendia.client.json.JsonEncounter; import org.projectbuendia.client.providers.Contracts.Observations; import org.projectbuendia.client.utils.Logger; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; /** * An encounter in the app model. Encounters contain one or more observations taken at a particular * timestamp. For more information on encounters and observations, see the official OpenMRS * documentation here: * <a href="https://wiki.openmrs.org/display/docs/Encounters+and+observations"> * https://wiki.openmrs.org/display/docs/Encounters+and+observations" * </a> * <p/> * <p>NOTE: Because of lack of typing info from the server, {@link Encounter} attempts to * determine the most appropriate type, but this typing is not guaranteed to succeed; also, * currently only <code>DATE</code> and <code>UUID</code> (coded) types are supported. */ @Immutable public class Encounter extends Base<String> { public final String patientUuid; public final @Nullable String encounterUuid; public final DateTime timestamp; public final Observation[] observations; public final String[] orderUuids; private static final Logger LOG = Logger.create(); /** * Creates a new Encounter for the given patient. * @param patientUuid The UUID of the patient. * @param encounterUuid The UUID of this encounter, or null for encounters created on the client. * @param timestamp The encounter time. * @param observations An array of observations to include in the encounter. * @param orderUuids A list of UUIDs of the orders executed during this encounter. */ public Encounter(String patientUuid, @Nullable String encounterUuid, DateTime timestamp, Observation[] observations, String[] orderUuids) { id = encounterUuid; this.patientUuid = patientUuid; this.encounterUuid = id; this.timestamp = timestamp; this.observations = observations == null ? new Observation[] {} : observations; this.orderUuids = orderUuids == null ? new String[] {} : orderUuids; } /** * Creates an instance of {@link Encounter} from a network * {@link JsonEncounter} object and corresponding patient UUID. */ public static Encounter fromJson(String patientUuid, JsonEncounter encounter) { List<Observation> observations = new ArrayList<Observation>(); if (encounter.observations != null) { for (Map.Entry<Object, Object> observation : encounter.observations.entrySet()) { observations.add(new Observation((String) observation.getKey(), (String) observation.getValue(), Observation.estimatedTypeFor((String) observation.getValue()))); } } return new Encounter(patientUuid, encounter.uuid, encounter.timestamp, observations.toArray(new Observation[observations.size()]), encounter.order_uuids); } /** Serializes this into a {@link JSONObject}. */ public JSONObject toJson() throws JSONException { JSONObject json = new JSONObject(); json.put(Server.PATIENT_UUID_KEY, patientUuid); json.put(Server.ENCOUNTER_TIMESTAMP, timestamp.getMillis() / 1000); if (observations.length > 0) { JSONArray observationsJson = new JSONArray(); for (Observation obs : observations) { JSONObject observationJson = new JSONObject(); observationJson.put(Server.OBSERVATION_QUESTION_UUID, obs.conceptUuid); String valueKey = obs.type == Observation.Type.DATE ? Server.OBSERVATION_ANSWER_DATE : Server.OBSERVATION_ANSWER_UUID; observationJson.put(valueKey, obs.value); observationsJson.put(observationJson); } json.put(Server.ENCOUNTER_OBSERVATIONS_KEY, observationsJson); } if (orderUuids.length > 0) { JSONArray orderUuidsJson = new JSONArray(); for (String orderUuid : orderUuids) { orderUuidsJson.put(orderUuid); } json.put(Server.ENCOUNTER_ORDER_UUIDS, orderUuidsJson); } return json; } /** * Converts this instance of {@link Encounter} to an array of * {@link android.content.ContentValues} objects for insertion into a database or content * provider. */ public ContentValues[] toContentValuesArray() { ContentValues[] cvs = new ContentValues[observations.length + orderUuids.length]; for (int i = 0; i < observations.length; i++) { Observation obs = observations[i]; ContentValues cv = new ContentValues(); cv.put(Observations.CONCEPT_UUID, obs.conceptUuid); cv.put(Observations.ENCOUNTER_MILLIS, timestamp.getMillis()); cv.put(Observations.ENCOUNTER_UUID, encounterUuid); cv.put(Observations.PATIENT_UUID, patientUuid); cv.put(Observations.VALUE, obs.value); cvs[i] = cv; } for (int i = 0; i < orderUuids.length; i++) { ContentValues cv = new ContentValues(); cv.put(Observations.CONCEPT_UUID, AppModel.ORDER_EXECUTED_CONCEPT_UUID); cv.put(Observations.ENCOUNTER_MILLIS, timestamp.getMillis()); cv.put(Observations.ENCOUNTER_UUID, encounterUuid); cv.put(Observations.PATIENT_UUID, patientUuid); cv.put(Observations.VALUE, orderUuids[i]); cvs[observations.length + i] = cv; } return cvs; } /** Represents a single observation within this encounter. */ public static final class Observation { public final String conceptUuid; public final String value; public final Type type; /** Data type of the observation. */ public enum Type { DATE, NON_DATE } public Observation(String conceptUuid, String value, Type type) { this.conceptUuid = conceptUuid; this.value = value; this.type = type; } /** * Produces a best guess for the type of a given value, since the server doesn't give us * typing information. */ public static Type estimatedTypeFor(String value) { try { new DateTime(Long.parseLong(value)); return Type.DATE; } catch (Exception e) { return Type.NON_DATE; } } } /** * An {@link CursorLoader} that loads {@link Encounter}s. Expects the {@link Cursor} to * contain only a single encounter, represented by multiple observations, with one observation per * row. * <p/> * <p>Unlike other {@link CursorLoader}s, {@link Encounter.Loader} must be instantiated * once per patient, since {@link Encounter} contains the patient's UUID as one of its fields, * which is not present in the database representation of an encounter. */ public static class Loader implements CursorLoader<Encounter> { private String mPatientUuid; public Loader(String patientUuid) { mPatientUuid = patientUuid; } @Override public Encounter fromCursor(Cursor cursor) { final String encounterUuid = cursor.getString(cursor.getColumnIndex(Observations.ENCOUNTER_UUID)); final long millis = cursor.getLong(cursor.getColumnIndex(Observations.ENCOUNTER_MILLIS)); List<Observation> observations = new ArrayList<>(); cursor.move(-1); while (cursor.moveToNext()) { String value = cursor.getString(cursor.getColumnIndex(Observations.VALUE)); observations.add(new Observation(cursor.getString(cursor.getColumnIndex(Observations.CONCEPT_UUID)), value, Observation.estimatedTypeFor(value))); } return new Encounter(mPatientUuid, encounterUuid, new DateTime(millis), observations.toArray(new Observation[observations.size()]), null); } } }