{"action":"created","comment":{"url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/pulls/comments/150533989","pull_request_review_id":76094700,"id":150533989,"diff_hunk":"@@ -0,0 +1,1125 @@\n+package util;\n+\n+import android.content.Context;\n+import android.content.SharedPreferences;\n+import android.os.AsyncTask;\n+import android.preference.PreferenceManager;\n+import android.util.Xml;\n+\n+import com.google.gson.Gson;\n+import com.google.gson.GsonBuilder;\n+\n+import org.json.JSONArray;\n+import org.json.JSONException;\n+import org.json.JSONObject;\n+import org.json.XML;\n+import org.smartregister.clientandeventmodel.Client;\n+import org.smartregister.clientandeventmodel.Event;\n+import org.smartregister.clientandeventmodel.FormAttributeParser;\n+import org.smartregister.clientandeventmodel.FormData;\n+import org.smartregister.clientandeventmodel.FormEntityConverter;\n+import org.smartregister.clientandeventmodel.FormField;\n+import org.smartregister.clientandeventmodel.FormInstance;\n+import org.smartregister.clientandeventmodel.SubFormData;\n+import org.smartregister.domain.FetchStatus;\n+import org.smartregister.domain.SyncStatus;\n+import org.smartregister.domain.form.FormSubmission;\n+import org.smartregister.domain.form.SubForm;\n+import org.smartregister.repository.AllSharedPreferences;\n+import org.smartregister.repository.BaseRepository;\n+import org.smartregister.repository.EventClientRepository;\n+import org.smartregister.tbr.activity.PresumptivePatientRegisterActivity;\n+import org.smartregister.tbr.application.TbrApplication;\n+import org.smartregister.tbr.sync.TbrClientProcessor;\n+import org.smartregister.util.AssetHandler;\n+import org.smartregister.util.Log;\n+import org.w3c.dom.Attr;\n+import org.w3c.dom.Document;\n+import org.w3c.dom.Element;\n+import org.w3c.dom.NamedNodeMap;\n+import org.w3c.dom.Node;\n+import org.w3c.dom.NodeList;\n+import org.xmlpull.v1.XmlSerializer;\n+\n+import java.io.ByteArrayInputStream;\n+import java.io.IOException;\n+import java.io.InputStream;\n+import java.io.StringWriter;\n+import java.text.Format;\n+import java.text.SimpleDateFormat;\n+import java.util.ArrayList;\n+import java.util.Date;\n+import java.util.List;\n+import java.util.Map;\n+import java.util.UUID;\n+\n+import javax.xml.parsers.DocumentBuilder;\n+import javax.xml.parsers.DocumentBuilderFactory;\n+\n+import static org.smartregister.util.Log.logError;\n+import static org.smartregister.util.Log.logInfo;\n+\n+/**\n+ * Created by samuelgithengi on 11/3/17.\n+ */\n+\n+public class EnketoFormUtils {\n+    public static final String TAG = \"FormUtils\";\n+    public static final String ecClientRelationships = \"ec_client_relationships.json\";\n+    private static final String shouldLoadValueKey = \"shouldLoadValue\";\n+    private static final String relationalIdKey = \"relational_id\";\n+    private static final String databaseIdKey = \"_id\";\n+    private static final String injectedBaseEntityIdKey = \"injectedBaseEntityId\";\n+    private static EnketoFormUtils instance;\n+    private Context mContext;\n+    private org.smartregister.Context theAppContext;\n+    private SimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd'T'HH:mm:ss.SSSZ\");\n+    private Format formatter = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n+    private FormEntityConverter formEntityConverter;\n+    private EventClientRepository eventClientRepository;\n+\n+    public EnketoFormUtils(Context context) {\n+        mContext = context;\n+        theAppContext = org.smartregister.Context.getInstance();\n+        FormAttributeParser formAttributeParser = new FormAttributeParser(context);\n+        formEntityConverter = new FormEntityConverter(formAttributeParser, mContext);\n+        eventClientRepository = TbrApplication.getInstance().getEventClientRepository();\n+    }\n+\n+    public static EnketoFormUtils getInstance(Context ctx) {\n+        if (instance == null) {\n+            instance = new EnketoFormUtils(ctx);\n+        }\n+\n+        return instance;\n+    }\n+\n+    private static JSONObject retrieveRelationshipJsonForLink(String link, JSONArray array)\n+            throws Exception {\n+        for (int i = 0; i < array.length(); i++) {\n+            JSONObject object = array.getJSONObject(i);\n+            if (relationShipExist(link, object)) {\n+                System.out.println(\"Relationship found ##\");\n+\n+                return object;\n+            }\n+        }\n+\n+        return null;\n+    }\n+\n+    private static boolean relationShipExist(String link, JSONObject json) {\n+        try {\n+            String[] path = link.split(\"\\\\.\");\n+            String parentTable = path[0];\n+            String childTable = path[1];\n+\n+            String jsonParentTableString = json.getString(\"parent\");\n+            String jsonChildTableString = json.getString(\"child\");\n+\n+            boolean parentToChildExist =\n+                    jsonParentTableString.equals(parentTable) && jsonChildTableString\n+                            .equals(childTable);\n+            boolean childToParentExist =\n+                    jsonParentTableString.equals(childTable) && jsonChildTableString\n+                            .equals(parentTable);\n+\n+            if (parentToChildExist || childToParentExist) {\n+                return true;\n+            }\n+\n+        } catch (Exception e) {\n+            android.util.Log.e(TAG, e.toString(), e);\n+        }\n+\n+        return false;\n+    }\n+\n+\n+    public FormSubmission generateFormSubmisionFromXMLString(String entity_id, String formData,\n+                                                             String formName, JSONObject\n+                                                                     overrides) throws Exception {\n+        JSONObject formSubmission = XML.toJSONObject(formData);\n+\n+        //FileUtilities fu = new FileUtilities();\n+        //fu.write(\"xmlform.txt\", formData);\n+        //fu.write(\"xmlformsubmission.txt\", formSubmission.toString());\n+        System.out.println(formSubmission);\n+\n+        // use the form_definition.json to iterate through fields\n+        String formDefinitionJson = readFileFromAssetsFolder(\n+                \"www/form/\" + formName + \"/form_definition.json\");\n+        JSONObject formDefinition = new JSONObject(formDefinitionJson);\n+\n+        String rootNodeKey = formSubmission.keys().next();\n+\n+        // retrieve the id, if it fails use the provided value by the param\n+        entity_id = formSubmission.getJSONObject(rootNodeKey).has(databaseIdKey) ? formSubmission\n+                .getJSONObject(rootNodeKey).getString(databaseIdKey) : generateRandomUUIDString();\n+\n+        //String bindPath = formDefinition.getJSONObject(\"form\").getString(\"bind_type\");\n+        JSONObject fieldsDefinition = formDefinition.getJSONObject(\"form\");\n+        JSONArray populatedFieldsArray = getPopulatedFieldsForArray(fieldsDefinition, entity_id,\n+                formSubmission, overrides);\n+\n+        // replace all the fields in the form\n+        formDefinition.getJSONObject(\"form\").put(\"fields\", populatedFieldsArray);\n+\n+        //get the subforms\n+        if (formDefinition.getJSONObject(\"form\").has(\"sub_forms\")) {\n+            JSONObject subFormDefinition = formDefinition.getJSONObject(\"form\").\n+                    getJSONArray(\"sub_forms\").getJSONObject(0);\n+            // get the bind path for the sub-form, helps us to locate the node that holds the data\n+            // in the corresponding data json\n+            String bindPath = subFormDefinition.getString(\"default_bind_path\");\n+\n+            // get the actual sub-form data\n+            JSONArray subFormDataArray = new JSONArray();\n+            Object subFormDataObject = getObjectAtPath(bindPath.split(\"/\"), formSubmission);\n+\n+            if (subFormDataObject instanceof JSONObject) {\n+                JSONObject subFormData = (JSONObject) subFormDataObject;\n+                subFormDataArray.put(0, subFormData);\n+            } else if (subFormDataObject instanceof JSONArray) {\n+                subFormDataArray = (JSONArray) subFormDataObject;\n+            }\n+\n+            JSONArray subForms = getSubForms(subFormDataArray, entity_id, subFormDefinition,\n+                    overrides);\n+\n+            // replace the subforms field with real data\n+            formDefinition.getJSONObject(\"form\").put(\"sub_forms\", subForms);\n+            //throw new Exception();\n+        }\n+\n+        String instanceId = generateRandomUUIDString();\n+        String entityId = retrieveIdForSubmission(formDefinition);\n+        String formDefinitionVersionString = formDefinition\n+                .getString(\"form_data_definition_version\");\n+\n+        String clientVersion = String.valueOf(new Date().getTime());\n+        String instance = formDefinition.toString();\n+        FormSubmission fs = new FormSubmission(instanceId, entityId, formName, instance,\n+                clientVersion, SyncStatus.PENDING, formDefinitionVersionString);\n+\n+        generateClientAndEventModelsForFormSubmission(fs, formName);\n+\n+        return fs;\n+    }\n+\n+    private void generateClientAndEventModelsForFormSubmission(FormSubmission formSubmission,\n+                                                               String formName) {\n+        org.smartregister.clientandeventmodel.FormSubmission v2FormSubmission;\n+\n+        String anmId = \"test\";//CoreLibrary.getInstance().context().anmService().fetchDetails().name();\n+        String instanceId = formSubmission.instanceId();\n+        String entityId = formSubmission.entityId();\n+        Long clientVersion = new Date().getTime();\n+        String formDataDefinitionVersion = formSubmission.formDataDefinitionVersion();\n+\n+        String bind_type = formSubmission.getFormInstance().getForm().getBind_type();\n+        String default_bind_path = formSubmission.getFormInstance().getForm()\n+                .getDefault_bind_path();\n+\n+        List<FormField> fields = convertFormFields(formSubmission.getFormInstance().getForm().\n+                getFields());\n+\n+        List<SubFormData> sub_forms = getSubFormList(formSubmission);\n+        FormData formData = new FormData(bind_type, default_bind_path, fields, sub_forms);\n+\n+        FormInstance formInstance = new FormInstance(formData);\n+        formInstance.setForm_data_definition_version(formDataDefinitionVersion);\n+\n+        v2FormSubmission = new org.smartregister.clientandeventmodel.FormSubmission(anmId,\n+                instanceId, formName, entityId, clientVersion, formDataDefinitionVersion,\n+                formInstance, clientVersion);\n+\n+        Event e = formEntityConverter.getEventFromFormSubmission(v2FormSubmission);\n+\n+        if (e.getEventType().equals(\"Screening\"))\n+            org.smartregister.util.Utils.startAsyncTask(new SavePatientAsyncTask(v2FormSubmission, mContext), null);\n+        else\n+            org.smartregister.util.Utils.startAsyncTask(new SaveEventAsyncTask(v2FormSubmission, mContext), null);\n+\n+    }\n+\n+    private void saveClient(Client client) {\n+        Log.logDebug(\"============== CLIENT ================\");\n+        Gson gson = new GsonBuilder().setDateFormat(\"yyyy-MM-dd'T'HH:mm:ss.SSSZ\").create();\n+        String clientJson = gson.toJson(client);\n+        Log.logDebug(clientJson);\n+        try {\n+            eventClientRepository.addorUpdateClient(client.getBaseEntityId(), new JSONObject(clientJson));\n+        } catch (JSONException e) {\n+            e.printStackTrace();\n+        }\n+        Log.logDebug(\"====================================\");\n+\n+    }\n+\n+    private void saveEvent(Event event) {\n+        Log.logDebug(\"============== EVENT ================\");\n+        Gson gson = new GsonBuilder().setDateFormat(\"yyyy-MM-dd'T'HH:mm:ss.SSSZ\").create();\n+        String eventJson = gson.toJson(event);\n+        Log.logDebug(eventJson);\n+        try {\n+            eventClientRepository.addEvent(event.getBaseEntityId(), new JSONObject(eventJson));\n+        } catch (JSONException e) {\n+            e.printStackTrace();\n+        }\n+    }\n+\n+    private List<SubFormData> getSubFormList(FormSubmission formSubmission) {\n+        List<SubFormData> sub_forms = new ArrayList<SubFormData>();\n+        List<SubForm> subForms = formSubmission.getFormInstance().getForm().getSub_forms();\n+        if (subForms != null) {\n+            for (SubForm sf : subForms) {\n+                SubFormData sd = new SubFormData();\n+                sd.setDefault_bind_path(sf.getDefaultBindPath());\n+                sd.setBind_type(sf.getBindType());\n+\n+                List<FormField> subFormFields = convertFormFields(sf.getFields());\n+                sd.setFields(subFormFields);\n+\n+                sd.setInstances(sf.getInstances());\n+                sd.setName(sf.getName());\n+                sub_forms.add(sd);\n+            }\n+        }\n+\n+        return sub_forms;\n+    }\n+\n+    private List<FormField> convertFormFields(List<org.smartregister.domain.form.FormField>\n+                                                      formFields) {\n+        List<FormField> fields = new ArrayList<FormField>();\n+        for (org.smartregister.domain.form.FormField ff : formFields) {\n+            FormField f = new FormField(ff.getName(), ff.getValue(), ff.getSource());\n+            fields.add(f);\n+        }\n+\n+        return fields;\n+    }\n+\n+    private JSONArray getSubForms(JSONArray subFormDataArray, String entity_id, JSONObject\n+            subFormDefinition, JSONObject overrides) throws Exception {\n+        JSONArray subForms = new JSONArray();\n+\n+        JSONArray subFormFields = getFieldsArrayForSubFormDefinition(subFormDefinition);\n+        JSONArray subFormInstances = new JSONArray();\n+\n+        // the id of each subform is contained in the attribute of the enclosing element\n+        for (int i = 0; i < subFormDataArray.length(); i++) {\n+            JSONObject subFormData = subFormDataArray.getJSONObject(i);\n+            String relationalId =\n+                    subFormData.has(relationalIdKey) ? subFormData.getString(relationalIdKey)\n+                            : entity_id;\n+            String id = subFormData.has(databaseIdKey) ? subFormData.getString(databaseIdKey)\n+                    : generateRandomUUIDString();\n+            JSONObject subFormInstance = getFieldValuesForSubFormDefinition(subFormDefinition,\n+                    relationalId, id, subFormData, overrides);\n+            subFormInstances.put(i, subFormInstance);\n+        }\n+\n+        subFormDefinition.put(\"instances\", subFormInstances);\n+        subFormDefinition.put(\"fields\", subFormFields);\n+        subForms.put(0, subFormDefinition);\n+\n+        return subForms;\n+    }\n+\n+\n+    private String generateRandomUUIDString() {\n+        return UUID.randomUUID().toString();\n+    }\n+\n+    private String retrieveIdForSubmission(JSONObject jsonObject) throws Exception {\n+        JSONArray fields = jsonObject.getJSONObject(\"form\").getJSONArray(\"fields\");\n+\n+        for (int i = 0; i < fields.length(); i++) {\n+            JSONObject field = fields.getJSONObject(i);\n+\n+            if (field.has(\"name\") && field.getString(\"name\").equalsIgnoreCase(\"id\")) {\n+                return field.getString(\"value\");\n+            }\n+        }\n+        return null;\n+    }\n+\n+    public Object getObjectAtPath(String[] path, JSONObject jsonObject) throws Exception {\n+        JSONObject object = jsonObject;\n+        int i = 0;\n+        while (i < path.length - 1) {\n+            if (object.has(path[i])) {\n+                Object o = object.get(path[i]);\n+                if (o instanceof JSONObject) {\n+                    object = object.getJSONObject(path[i]);\n+                } else if (o instanceof JSONArray) {\n+                    object = object.getJSONArray(path[i]).getJSONObject(0);\n+                }\n+            }\n+            i++;\n+        }\n+        return object.has(path[i]) ? object.get(path[i]) : null;\n+    }\n+\n+    public JSONArray getPopulatedFieldsForArray(JSONObject fieldsDefinition, String entityId,\n+                                                JSONObject jsonObject, JSONObject overrides)\n+            throws Exception {\n+        String bindPath = fieldsDefinition.getString(\"bind_type\");\n+        String sql = \"select * from \" + bindPath + \" where id='\" + entityId + \"'\";\n+        String dbEntity = theAppContext.formDataRepository().queryUniqueResult(sql);\n+\n+        JSONObject entityJson = new JSONObject();\n+\n+        if (dbEntity != null && !dbEntity.isEmpty()) {\n+            entityJson = new JSONObject(dbEntity);\n+        }\n+\n+        JSONArray fieldsArray = fieldsDefinition.getJSONArray(\"fields\");\n+\n+        for (int i = 0; i < fieldsArray.length(); i++) {\n+            JSONObject item = fieldsArray.getJSONObject(i);\n+\n+            if (!item.has(\"name\")) {\n+                continue; // skip elements without name\n+            }\n+\n+            String itemName = item.getString(\"name\");\n+            boolean shouldLoadValue =\n+                    item.has(\"shouldLoadValue\") && item.getBoolean(\"shouldLoadValue\");\n+\n+            if (item.has(\"bind\")) {\n+                String pathSting = item.getString(\"bind\");\n+                pathSting = pathSting.startsWith(\"/\") ? pathSting.substring(1) : pathSting;\n+                String[] path = pathSting.split(\"/\");\n+                String value = getValueForPath(path, jsonObject);\n+                item.put(\"value\", value);\n+            }\n+\n+            if (shouldLoadValue && overrides.has(item.getString(\"name\"))) {\n+                // if the value is not set use the value in the overrides filed\n+                if (!item.has(\"value\")) {\n+                    item.put(\"value\", overrides.getString(item.getString(\"name\")));\n+                }\n+            }\n+\n+            // map the id field for child elements\n+            if (isForeignIdPath(item)) {\n+                String value = null;\n+                if (entityJson.length() > 0 && shouldLoadValue) {\n+                    //retrieve the child attributes\n+                    value = retrieveValueForLinkedRecord(item.getString(\"source\"), entityJson);\n+                }\n+\n+                // generate uuid if its still not available\n+                if (item.getString(\"source\").endsWith(\".id\") && value == null) {\n+                    value = generateRandomUUIDString();\n+                }\n+\n+                if (value != null && !item.has(\"value\")) {\n+                    item.put(\"value\", value);\n+                }\n+            }\n+\n+            // add source property if not available\n+            if (!item.has(\"source\")) {\n+                item.put(\"source\", bindPath + \".\" + item.getString(\"name\"));\n+            }\n+\n+            if (itemName.equalsIgnoreCase(\"id\") && !isForeignIdPath(item)) {\n+                assert entityId != null;\n+                item.put(\"value\", entityId);\n+            }\n+\n+            if (itemName.equalsIgnoreCase(injectedBaseEntityIdKey)) {\n+                assert entityId != null;\n+                item.put(\"value\", entityId);\n+            }\n+\n+            if (itemName.equalsIgnoreCase(\"start\") || itemName.equalsIgnoreCase(\"end\")) {\n+                try {\n+                    boolean isEndTime = itemName.equalsIgnoreCase(\"end\");\n+                    String val =\n+                            item.has(\"value\") ? item.getString(\"value\") : sdf.format(new Date());\n+\n+                    if (isEndTime) {\n+                        val = formatter.format(new Date());\n+                    } else {\n+                        Date d = sdf.parse(val);\n+                        //parse the date to match OpenMRS format\n+                        val = formatter.format(d);\n+                    }\n+\n+                    item.put(\"value\", val);\n+                } catch (Exception e) {\n+                    android.util.Log.e(TAG, e.toString(), e);\n+                }\n+            }\n+        }\n+        return fieldsArray;\n+    }\n+\n+    private boolean isForeignIdPath(JSONObject item) throws Exception {\n+        // e.g ibu.anak.id\n+        return item.has(\"source\") && item.getString(\"source\").split(\"\\\\.\").length > 2;\n+    }\n+\n+    public String retrieveValueForLinkedRecord(String link, JSONObject entityJson) {\n+        try {\n+            String entityRelationships = readFileFromAssetsFolder(\n+                    \"www/form/entity_relationship\" + \".json\");\n+            JSONArray json = new JSONArray(entityRelationships);\n+            logInfo(json.toString());\n+\n+            JSONObject rJson;\n+\n+            if ((rJson = retrieveRelationshipJsonForLink(link, json)) != null) {\n+                String[] path = link.split(\"\\\\.\");\n+                String parentTable = path[0];\n+                String childTable = path[1];\n+\n+                String joinValueKey =\n+                        parentTable.equals(rJson.getString(\"parent\")) ? rJson.getString(\"from\")\n+                                : rJson.getString(\"to\");\n+                joinValueKey = joinValueKey.contains(\".\") ? joinValueKey\n+                        .substring(joinValueKey.lastIndexOf(\".\") + 1) : joinValueKey;\n+\n+                String val = entityJson.getString(joinValueKey);\n+\n+                String joinField =\n+                        parentTable.equals(rJson.getString(\"parent\")) ? rJson.getString(\"to\")\n+                                : rJson.getString(\"from\");\n+                String sql =\n+                        \"select * from \" + childTable + \" where \" + joinField + \"='\" + val + \"'\";\n+                logInfo(sql);\n+                String dbEntity = theAppContext.formDataRepository().queryUniqueResult(sql);\n+                JSONObject linkedEntityJson = new JSONObject();\n+\n+                if (dbEntity != null && !dbEntity.isEmpty()) {\n+                    linkedEntityJson = new JSONObject(dbEntity);\n+                }\n+\n+                // finally retrieve the value from the child entity, need to improve or remove\n+                // entirely these hacks\n+                String sourceKey = link.substring(link.lastIndexOf(\".\") + 1);\n+\n+                if (linkedEntityJson.has(sourceKey)) {\n+                    return linkedEntityJson.getString(sourceKey);\n+                }\n+            }\n+\n+        } catch (Exception e) {\n+            android.util.Log.e(TAG, e.toString(), e);\n+        }\n+        return null;\n+    }\n+\n+    public JSONArray getFieldsArrayForSubFormDefinition(JSONObject fieldsDefinition) throws\n+            Exception {\n+        JSONArray fieldsArray = fieldsDefinition.getJSONArray(\"fields\");\n+        String bindPath = fieldsDefinition.getString(\"bind_type\");\n+\n+        JSONArray subFormFieldsArray = new JSONArray();\n+\n+        for (int i = 0; i < fieldsArray.length(); i++) {\n+            JSONObject field = new JSONObject();\n+            JSONObject item = fieldsArray.getJSONObject(i);\n+\n+            if (!item.has(\"name\")) {\n+                continue; // skip elements without name\n+            }\n+\n+            field.put(\"name\", item.getString(\"name\"));\n+\n+            if (!item.has(\"source\")) {\n+                field.put(\"source\", bindPath + \".\" + item.getString(\"name\"));\n+            } else {\n+                field.put(\"source\", bindPath + \".\" + item.getString(\"source\"));\n+            }\n+\n+            subFormFieldsArray.put(i, field);\n+        }\n+\n+        return subFormFieldsArray;\n+    }\n+\n+    public JSONObject getFieldValuesForSubFormDefinition(JSONObject fieldsDefinition, String\n+            relationalId, String entityId, JSONObject jsonObject, JSONObject overrides) throws\n+            Exception {\n+\n+        JSONArray fieldsArray = fieldsDefinition.getJSONArray(\"fields\");\n+\n+        JSONObject fieldsValues = new JSONObject();\n+\n+        for (int i = 0; i < fieldsArray.length(); i++) {\n+            JSONObject item = fieldsArray.getJSONObject(i);\n+\n+            if (!item.has(\"name\")) {\n+                continue; // skip elements without name\n+            }\n+\n+            if (item.has(\"bind\")) {\n+                String pathSting = item.getString(\"bind\");\n+                pathSting = pathSting.startsWith(\"/\") ? pathSting.substring(1) : pathSting;\n+                String[] path = pathSting.split(\"/\");\n+\n+                //check if we need to override this val\n+                if (overrides.has(item.getString(\"name\"))) {\n+                    fieldsValues.put(item.getString(\"name\"),\n+                            overrides.getString(item.getString(\"name\")));\n+                } else {\n+                    String value = getValueForPath(path, jsonObject);\n+                    fieldsValues.put(item.getString(\"name\"), value);\n+                }\n+            }\n+\n+            //TODO: generate the id for the record\n+            if (item.has(\"name\") && item.getString(\"name\").equalsIgnoreCase(\"id\")) {\n+                String id = entityId != null ? entityId : generateRandomUUIDString();\n+                fieldsValues.put(item.getString(\"name\"), id);\n+            }\n+\n+            //TODO: generate the relational for the record\n+            if (item.has(\"name\") && item.getString(\"name\").equalsIgnoreCase(relationalIdKey)) {\n+                fieldsValues.put(item.getString(\"name\"), relationalId);\n+            }\n+\n+            //TODO: generate the injectedBaseEntityIdKey for the record\n+            if (item.has(\"name\") && item.getString(\"name\")\n+                    .equalsIgnoreCase(injectedBaseEntityIdKey)) {\n+                fieldsValues.put(item.getString(\"name\"), relationalId);\n+            }\n+\n+            populateRelationField(item, fieldsValues, relationalId);\n+        }\n+        return fieldsValues;\n+    }\n+\n+    private String getECClientRelationships() {\n+        return AssetHandler.readFileFromAssetsFolder(ecClientRelationships, mContext);\n+    }\n+\n+    /**\n+     * see if the current field is a client_relationship field, if so set it's value to the\n+     * relationId since that's the parent base_entity_id\n+     *\n+     * @param fieldItem\n+     * @param fieldsValues\n+     * @param relationalId\n+     */\n+    private void populateRelationField(JSONObject fieldItem, JSONObject fieldsValues, String\n+            relationalId) {\n+        try {\n+            if (fieldItem.has(\"name\")) {\n+                String fieldName = fieldItem.getString(\"name\");\n+                String relationships = getECClientRelationships();\n+                JSONArray jsonArray = new JSONArray(relationships);\n+                for (int i = 0; i < jsonArray.length(); i++) {\n+                    JSONObject rObject = jsonArray.getJSONObject(i);\n+                    if (rObject.has(\"field\") && rObject.getString(\"field\")\n+                            .equalsIgnoreCase(fieldName)) {\n+                        fieldsValues.put(fieldName, relationalId);\n+                    }\n+                }\n+            }\n+\n+        } catch (JSONException e) {\n+            android.util.Log.e(TAG, e.toString(), e);\n+        }\n+    }\n+\n+    public String getValueForPath(String[] path, JSONObject jsonObject) throws Exception {\n+        JSONObject object = jsonObject;\n+        String value = null;\n+        int i = 0;\n+\n+        while (i < path.length - 1) {\n+            if (object.has(path[i])) {\n+                Object o = object.get(path[i]);\n+                if (o instanceof JSONObject) {\n+                    object = object.getJSONObject(path[i]);\n+                } else if (o instanceof JSONArray) {\n+                    object = object.getJSONArray(path[i]).getJSONObject(0);\n+                }\n+            }\n+\n+            i++;\n+        }\n+        Object valueObject = object.has(path[i]) ? object.get(path[i]) : null;\n+\n+        if (valueObject == null) {\n+            return value;\n+        }\n+        if (valueObject instanceof JSONObject && ((JSONObject) valueObject).has(\"content\")) {\n+            value = ((JSONObject) object.get(path[i])).getString(\"content\");\n+        } else if (valueObject instanceof JSONArray) {\n+            value = ((JSONArray) valueObject).get(0).toString();\n+        } else if (!(valueObject instanceof JSONObject)) {\n+            value = valueObject.toString();\n+        }\n+\n+        return value;\n+    }\n+\n+    private String readFileFromAssetsFolder(String fileName) {\n+        String fileContents = null;\n+        try {\n+            InputStream is = mContext.getAssets().open(fileName);\n+            int size = is.available();\n+            byte[] buffer = new byte[size];\n+            is.read(buffer);\n+            is.close();\n+            fileContents = new String(buffer, \"UTF-8\");\n+        } catch (IOException ex) {\n+            android.util.Log.e(TAG, ex.toString(), ex);\n+\n+            return null;\n+        }\n+\n+        //Log.d(\"File\", fileContents);\n+\n+        return fileContents;\n+    }\n+\n+    public String generateXMLInputForFormWithEntityId(String entityId, String formName, String\n+            overrides) {\n+        try {\n+            // get the field overrides map\n+            JSONObject fieldOverrides = new JSONObject();\n+            if (overrides != null) {\n+                fieldOverrides = new JSONObject(overrides);\n+                String overridesStr = fieldOverrides.getString(\"fieldOverrides\");\n+                fieldOverrides = new JSONObject(overridesStr);\n+            }\n+\n+            // use the form_definition.json to get the form mappings\n+            String formDefinitionJson = readFileFromAssetsFolder(\n+                    \"www/form/\" + formName + \"/form_definition.json\");\n+            JSONObject formDefinition = new JSONObject(formDefinitionJson);\n+            String ec_bind_path = formDefinition.getJSONObject(\"form\").getString(\"ec_bind_type\");\n+\n+            String sql =\n+                    \"select * from \" + ec_bind_path + \" where base_entity_id='\" + entityId + \"'\";\n+            Map<String, String> dbEntity = theAppContext.formDataRepository().\n+                    getMapFromSQLQuery(sql);\n+            Map<String, String> detailsMap = theAppContext.detailsRepository().\n+                    getAllDetailsForClient(entityId);\n+            detailsMap.putAll(dbEntity);\n+\n+            JSONObject entityJson = new JSONObject();\n+            if (detailsMap != null && !detailsMap.isEmpty()) {\n+                entityJson = new JSONObject(detailsMap);\n+            }\n+\n+            //read the xml form model, the expected form model that is passed to the form mirrors it\n+            String formModelString = readFileFromAssetsFolder(\n+                    \"www/form/\" + formName + \"/model\" + \".xml\").replaceAll(\"\\n\", \" \")\n+                    .replaceAll(\"\\r\", \" \");\n+            InputStream is = new ByteArrayInputStream(formModelString.getBytes());\n+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\n+            dbf.setValidating(false);\n+            DocumentBuilder db = dbf.newDocumentBuilder();\n+            Document document = db.parse(is);\n+\n+            XmlSerializer serializer = Xml.newSerializer();\n+            StringWriter writer = new StringWriter();\n+            serializer.setOutput(writer);\n+            serializer.startDocument(\"UTF-8\", true);\n+\n+            //skip processing <model><instance>\n+            NodeList els = ((Element) document.getElementsByTagName(\"model\").item(0)).\n+                    getElementsByTagName(\"instance\");\n+            Element el = (Element) els.item(0);\n+            NodeList entries = el.getChildNodes();\n+            int num = entries.getLength();\n+            for (int i = 0; i < num; i++) {\n+                Node n = entries.item(i);\n+                if (n instanceof Element) {\n+                    Element node = (Element) n;\n+                    writeXML(node, serializer, fieldOverrides, formDefinition, entityJson, null);\n+                }\n+            }\n+\n+            serializer.endDocument();\n+\n+            String xml = writer.toString();\n+            // Add model and instance tags\n+            xml = xml.substring(56);\n+            System.out.println(xml);\n+\n+            return xml;\n+\n+        } catch (Exception e) {\n+            android.util.Log.e(TAG, e.toString(), e);\n+        }\n+        return \"\";\n+    }\n+\n+    private void writeXML(Element node, XmlSerializer serializer, JSONObject fieldOverrides,\n+                          JSONObject formDefinition, JSONObject entityJson, String parentId) {\n+        try {\n+            String nodeName = node.getNodeName();\n+            String entityId =\n+                    entityJson.has(\"id\") ? entityJson.getString(\"id\") : generateRandomUUIDString();\n+            String relationalId =\n+                    entityJson.has(relationalIdKey) ? entityJson.getString(relationalIdKey)\n+                            : parentId;\n+\n+            serializer.startTag(\"\", nodeName);\n+\n+            // write the xml attributes\n+            writeXMLAttributes(node, serializer, entityId, relationalId);\n+\n+            String nodeValue = retrieveValueForNodeName(nodeName, entityJson, formDefinition);\n+            //overwrite the node value with contents from overrides map\n+            if (fieldOverrides.has(nodeName)) {\n+                nodeValue = fieldOverrides.getString(nodeName);\n+            }\n+            //write the node value\n+            if (nodeValue != null) {\n+                serializer.text(nodeValue);\n+            }\n+\n+            List<String> subFormNames = getSubFormNames(formDefinition);\n+\n+            // get all child nodes\n+            NodeList entries = node.getChildNodes();\n+            int num = entries.getLength();\n+            for (int i = 0; i < num; i++) {\n+                if (entries.item(i) instanceof Element) {\n+                    Element child = (Element) entries.item(i);\n+                    String fieldName = child.getNodeName();\n+\n+                    // its a subform element process it\n+                    if (!subFormNames.isEmpty() && subFormNames.contains(fieldName)) {\n+                        // its a subform element process it\n+                        // get the subform definition\n+                        JSONArray subForms = formDefinition.getJSONObject(\"form\").\n+                                getJSONArray(\"sub_forms\");\n+                        JSONObject subFormDefinition = retriveSubformDefinitionForBindPath(subForms,\n+                                fieldName);\n+                        if (subFormDefinition != null) {\n+\n+                            String childTableName = subFormDefinition.getString(\"ec_bind_type\");\n+                            String sql = \"select * from '\" + childTableName + \"' where \"\n+                                    + \"relational_id = '\" + entityId + \"'\";\n+                            String childRecordsString = theAppContext.formDataRepository().\n+                                    queryList(sql);\n+                            JSONArray childRecords = new JSONArray(childRecordsString);\n+\n+                            JSONArray fieldsArray = subFormDefinition.getJSONArray(\"fields\");\n+                            // check whether we are supposed to load the id of the child record\n+                            JSONObject idFieldDefn = getJsonFieldFromArray(\"id\", fieldsArray);\n+\n+                            // definition for id\n+                            boolean shouldLoadId =\n+                                    idFieldDefn.has(shouldLoadValueKey) && idFieldDefn\n+                                            .getBoolean(shouldLoadValueKey);\n+\n+                            if (shouldLoadId && childRecords.length() > 0) {\n+                                for (int k = 0; k < childRecords.length(); k++) {\n+                                    JSONObject childEntityJson = childRecords.getJSONObject(k);\n+                                    JSONObject obj = getCombinedJsonObjectForObject(\n+                                            childEntityJson);\n+                                    writeXML(child, serializer, fieldOverrides, subFormDefinition,\n+                                            childEntityJson, entityId);\n+                                }\n+\n+                            }\n+                        }\n+                    } else {\n+                        // it's not a sub-form element write its value\n+                        serializer.startTag(\"\", fieldName);\n+                        // write the xml attributes\n+                        // a value node doesn't have id or relationalId fields\n+                        writeXMLAttributes(child, serializer, null, null);\n+                        // write the node value\n+                        String value = retrieveValueForNodeName(fieldName, entityJson,\n+                                formDefinition);\n+                        // write the node value\n+                        if (value != null) {\n+                            serializer.text(value);\n+                        }\n+\n+                        // overwrite the node value with contents from overrides map\n+                        if (fieldOverrides.has(fieldName)) {\n+                            serializer.text(fieldOverrides.getString(fieldName));\n+                        }\n+\n+                        serializer.endTag(\"\", fieldName);\n+                    }\n+                }\n+            }\n+\n+            serializer.endTag(\"\", node.getNodeName());\n+\n+        } catch (Exception e) {\n+            throw new RuntimeException(e);\n+        }\n+    }\n+\n+    private void writeXMLAttributes(Element node, XmlSerializer serializer, String id, String\n+            relationalId) {\n+        try {\n+            // get a map containing the attributes of this node\n+            NamedNodeMap attributes = node.getAttributes();\n+\n+            // get the number of nodes in this map\n+            int numAttrs = attributes.getLength();\n+\n+            if (id != null) {\n+                serializer.attribute(\"\", databaseIdKey, id);\n+            }\n+\n+            if (relationalId != null) {\n+                serializer.attribute(\"\", relationalIdKey, relationalId);\n+            }\n+\n+            for (int i = 0; i < numAttrs; i++) {\n+                Attr attr = (Attr) attributes.item(i);\n+                String attrName = attr.getNodeName();\n+                String attrValue = attr.getNodeValue();\n+                serializer.attribute(\"\", attrName, attrValue);\n+            }\n+\n+        } catch (Exception e) {\n+            throw new RuntimeException(e);\n+        }\n+    }\n+\n+    /**\n+     * retrieves node value for cases which the nodename don't match the name of the xml element\n+     *\n+     * @param nodeName\n+     * @param entityJson\n+     * @param formDefinition\n+     * @return\n+     */\n+    private String retrieveValueForNodeName(String nodeName, JSONObject entityJson, JSONObject","path":"opensrp-tbr/src/main/java/util/EnketoFormUtils.java","position":899,"original_position":899,"commit_id":"de6a0df094da9e47ced58780a483021b39fe9fd1","original_commit_id":"de6a0df094da9e47ced58780a483021b39fe9fd1","user":{"login":"codacy-bot","id":19940114,"avatar_url":"https://avatars1.githubusercontent.com/u/19940114?v=4","gravatar_id":"","url":"https://api.github.com/users/codacy-bot","html_url":"https://github.com/codacy-bot","followers_url":"https://api.github.com/users/codacy-bot/followers","following_url":"https://api.github.com/users/codacy-bot/following{/other_user}","gists_url":"https://api.github.com/users/codacy-bot/gists{/gist_id}","starred_url":"https://api.github.com/users/codacy-bot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/codacy-bot/subscriptions","organizations_url":"https://api.github.com/users/codacy-bot/orgs","repos_url":"https://api.github.com/users/codacy-bot/repos","events_url":"https://api.github.com/users/codacy-bot/events{/privacy}","received_events_url":"https://api.github.com/users/codacy-bot/received_events","type":"User","site_admin":false},"body":"![Codacy](https://www.codacy.com/assets/images/favicon.png) Issue found: [The method retrieveValueForNodeName() has an NPath complexity of 2946](https://www.codacy.com/app/OpenSRP/opensrp-client-tbr/pullRequest?prid=1053860)","created_at":"2017-11-13T13:12:40Z","updated_at":"2017-11-13T13:12:40Z","html_url":"https://github.com/OpenSRP/opensrp-client-tbr/pull/33#discussion_r150533989","pull_request_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/pulls/33","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/pulls/comments/150533989"},"html":{"href":"https://github.com/OpenSRP/opensrp-client-tbr/pull/33#discussion_r150533989"},"pull_request":{"href":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/pulls/33"}}},"pull_request":{"url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/pulls/33","id":151148837,"html_url":"https://github.com/OpenSRP/opensrp-client-tbr/pull/33","diff_url":"https://github.com/OpenSRP/opensrp-client-tbr/pull/33.diff","patch_url":"https://github.com/OpenSRP/opensrp-client-tbr/pull/33.patch","issue_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/issues/33","number":33,"state":"open","locked":false,"title":"Implement Presumptive Patients Register","user":{"login":"githengi","id":25123762,"avatar_url":"https://avatars1.githubusercontent.com/u/25123762?v=4","gravatar_id":"","url":"https://api.github.com/users/githengi","html_url":"https://github.com/githengi","followers_url":"https://api.github.com/users/githengi/followers","following_url":"https://api.github.com/users/githengi/following{/other_user}","gists_url":"https://api.github.com/users/githengi/gists{/gist_id}","starred_url":"https://api.github.com/users/githengi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/githengi/subscriptions","organizations_url":"https://api.github.com/users/githengi/orgs","repos_url":"https://api.github.com/users/githengi/repos","events_url":"https://api.github.com/users/githengi/events{/privacy}","received_events_url":"https://api.github.com/users/githengi/received_events","type":"User","site_admin":false},"body":"Implement Presumptive Patients Register\r\n\r\n**Commit Summary**\r\n\r\n- Implemented Presumptive Patients Register\r\n- Added Screening form to add patients to the Presumptive Register\r\n- Save the patient Data from the Enketo Screening form using the EC model\r\n- Add Enketo forms for capturing test results of a patient \r\n- Display Test Results on the Presumptive register\r\n- Refactor login screen for better display on 5 inch phones","created_at":"2017-11-07T15:43:55Z","updated_at":"2017-11-13T13:12:40Z","closed_at":null,"merged_at":null,"merge_commit_sha":"bb46376f04e983e33533a420cf45f70f9ae6877d","assignee":null,"assignees":[],"requested_reviewers":[{"login":"keymane","id":13656416,"avatar_url":"https://avatars3.githubusercontent.com/u/13656416?v=4","gravatar_id":"","url":"https://api.github.com/users/keymane","html_url":"https://github.com/keymane","followers_url":"https://api.github.com/users/keymane/followers","following_url":"https://api.github.com/users/keymane/following{/other_user}","gists_url":"https://api.github.com/users/keymane/gists{/gist_id}","starred_url":"https://api.github.com/users/keymane/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/keymane/subscriptions","organizations_url":"https://api.github.com/users/keymane/orgs","repos_url":"https://api.github.com/users/keymane/repos","events_url":"https://api.github.com/users/keymane/events{/privacy}","received_events_url":"https://api.github.com/users/keymane/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/pulls/33/commits","review_comments_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/pulls/33/comments","review_comment_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/pulls/comments{/number}","comments_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/issues/33/comments","statuses_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/statuses/de6a0df094da9e47ced58780a483021b39fe9fd1","head":{"label":"OpenSRP:issue25","ref":"issue25","sha":"de6a0df094da9e47ced58780a483021b39fe9fd1","user":{"login":"OpenSRP","id":7898027,"avatar_url":"https://avatars1.githubusercontent.com/u/7898027?v=4","gravatar_id":"","url":"https://api.github.com/users/OpenSRP","html_url":"https://github.com/OpenSRP","followers_url":"https://api.github.com/users/OpenSRP/followers","following_url":"https://api.github.com/users/OpenSRP/following{/other_user}","gists_url":"https://api.github.com/users/OpenSRP/gists{/gist_id}","starred_url":"https://api.github.com/users/OpenSRP/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OpenSRP/subscriptions","organizations_url":"https://api.github.com/users/OpenSRP/orgs","repos_url":"https://api.github.com/users/OpenSRP/repos","events_url":"https://api.github.com/users/OpenSRP/events{/privacy}","received_events_url":"https://api.github.com/users/OpenSRP/received_events","type":"Organization","site_admin":false},"repo":{"id":90995053,"name":"opensrp-client-tbr","full_name":"OpenSRP/opensrp-client-tbr","owner":{"login":"OpenSRP","id":7898027,"avatar_url":"https://avatars1.githubusercontent.com/u/7898027?v=4","gravatar_id":"","url":"https://api.github.com/users/OpenSRP","html_url":"https://github.com/OpenSRP","followers_url":"https://api.github.com/users/OpenSRP/followers","following_url":"https://api.github.com/users/OpenSRP/following{/other_user}","gists_url":"https://api.github.com/users/OpenSRP/gists{/gist_id}","starred_url":"https://api.github.com/users/OpenSRP/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OpenSRP/subscriptions","organizations_url":"https://api.github.com/users/OpenSRP/orgs","repos_url":"https://api.github.com/users/OpenSRP/repos","events_url":"https://api.github.com/users/OpenSRP/events{/privacy}","received_events_url":"https://api.github.com/users/OpenSRP/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/OpenSRP/opensrp-client-tbr","description":null,"fork":false,"url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr","forks_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/forks","keys_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/keys{/key_id}","collaborators_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/teams","hooks_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/hooks","issue_events_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/issues/events{/number}","events_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/events","assignees_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/assignees{/user}","branches_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/branches{/branch}","tags_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/tags","blobs_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/git/refs{/sha}","trees_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/git/trees{/sha}","statuses_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/statuses/{sha}","languages_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/languages","stargazers_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/stargazers","contributors_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/contributors","subscribers_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/subscribers","subscription_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/subscription","commits_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/commits{/sha}","git_commits_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/git/commits{/sha}","comments_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/comments{/number}","issue_comment_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/issues/comments{/number}","contents_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/contents/{+path}","compare_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/compare/{base}...{head}","merges_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/merges","archive_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/downloads","issues_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/issues{/number}","pulls_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/pulls{/number}","milestones_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/milestones{/number}","notifications_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/labels{/name}","releases_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/releases{/id}","deployments_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/deployments","created_at":"2017-05-11T15:29:49Z","updated_at":"2017-08-24T09:41:10Z","pushed_at":"2017-11-13T13:09:28Z","git_url":"git://github.com/OpenSRP/opensrp-client-tbr.git","ssh_url":"git@github.com:OpenSRP/opensrp-client-tbr.git","clone_url":"https://github.com/OpenSRP/opensrp-client-tbr.git","svn_url":"https://github.com/OpenSRP/opensrp-client-tbr","homepage":null,"size":2059,"stargazers_count":1,"watchers_count":1,"language":"Java","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1,"mirror_url":null,"archived":false,"open_issues_count":28,"forks":1,"open_issues":28,"watchers":1,"default_branch":"master"}},"base":{"label":"OpenSRP:master","ref":"master","sha":"7bc989730d1a685dfbda379ae3abf38bab28c38a","user":{"login":"OpenSRP","id":7898027,"avatar_url":"https://avatars1.githubusercontent.com/u/7898027?v=4","gravatar_id":"","url":"https://api.github.com/users/OpenSRP","html_url":"https://github.com/OpenSRP","followers_url":"https://api.github.com/users/OpenSRP/followers","following_url":"https://api.github.com/users/OpenSRP/following{/other_user}","gists_url":"https://api.github.com/users/OpenSRP/gists{/gist_id}","starred_url":"https://api.github.com/users/OpenSRP/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OpenSRP/subscriptions","organizations_url":"https://api.github.com/users/OpenSRP/orgs","repos_url":"https://api.github.com/users/OpenSRP/repos","events_url":"https://api.github.com/users/OpenSRP/events{/privacy}","received_events_url":"https://api.github.com/users/OpenSRP/received_events","type":"Organization","site_admin":false},"repo":{"id":90995053,"name":"opensrp-client-tbr","full_name":"OpenSRP/opensrp-client-tbr","owner":{"login":"OpenSRP","id":7898027,"avatar_url":"https://avatars1.githubusercontent.com/u/7898027?v=4","gravatar_id":"","url":"https://api.github.com/users/OpenSRP","html_url":"https://github.com/OpenSRP","followers_url":"https://api.github.com/users/OpenSRP/followers","following_url":"https://api.github.com/users/OpenSRP/following{/other_user}","gists_url":"https://api.github.com/users/OpenSRP/gists{/gist_id}","starred_url":"https://api.github.com/users/OpenSRP/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OpenSRP/subscriptions","organizations_url":"https://api.github.com/users/OpenSRP/orgs","repos_url":"https://api.github.com/users/OpenSRP/repos","events_url":"https://api.github.com/users/OpenSRP/events{/privacy}","received_events_url":"https://api.github.com/users/OpenSRP/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/OpenSRP/opensrp-client-tbr","description":null,"fork":false,"url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr","forks_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/forks","keys_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/keys{/key_id}","collaborators_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/teams","hooks_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/hooks","issue_events_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/issues/events{/number}","events_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/events","assignees_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/assignees{/user}","branches_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/branches{/branch}","tags_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/tags","blobs_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/git/refs{/sha}","trees_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/git/trees{/sha}","statuses_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/statuses/{sha}","languages_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/languages","stargazers_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/stargazers","contributors_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/contributors","subscribers_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/subscribers","subscription_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/subscription","commits_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/commits{/sha}","git_commits_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/git/commits{/sha}","comments_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/comments{/number}","issue_comment_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/issues/comments{/number}","contents_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/contents/{+path}","compare_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/compare/{base}...{head}","merges_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/merges","archive_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/downloads","issues_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/issues{/number}","pulls_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/pulls{/number}","milestones_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/milestones{/number}","notifications_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/labels{/name}","releases_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/releases{/id}","deployments_url":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/deployments","created_at":"2017-05-11T15:29:49Z","updated_at":"2017-08-24T09:41:10Z","pushed_at":"2017-11-13T13:09:28Z","git_url":"git://github.com/OpenSRP/opensrp-client-tbr.git","ssh_url":"git@github.com:OpenSRP/opensrp-client-tbr.git","clone_url":"https://github.com/OpenSRP/opensrp-client-tbr.git","svn_url":"https://github.com/OpenSRP/opensrp-client-tbr","homepage":null,"size":2059,"stargazers_count":1,"watchers_count":1,"language":"Java","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1,"mirror_url":null,"archived":false,"open_issues_count":28,"forks":1,"open_issues":28,"watchers":1,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/pulls/33"},"html":{"href":"https://github.com/OpenSRP/opensrp-client-tbr/pull/33"},"issue":{"href":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/issues/33"},"comments":{"href":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/issues/33/comments"},"review_comments":{"href":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/pulls/33/comments"},"review_comment":{"href":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/pulls/33/commits"},"statuses":{"href":"https://api.github.com/repos/OpenSRP/opensrp-client-tbr/statuses/de6a0df094da9e47ced58780a483021b39fe9fd1"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"codacy-bot"}}