de.uni_koblenz_landau.apow.ObsDetailFragment.java Source code

Java tutorial

Introduction

Here is the source code for de.uni_koblenz_landau.apow.ObsDetailFragment.java

Source

/**
 * Apow - a mobile EHR Management System for low-resource environments
 * in developing countries, exemplified by rural Ghana
 * Copyright (C) 2014 Martin Landua
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses/.
 */

package de.uni_koblenz_landau.apow;

import java.util.ArrayList;
import java.util.List;

import org.openmrs.Concept;
import org.openmrs.ConceptDatatype;
import org.openmrs.ConceptNumeric;
import org.openmrs.Encounter;
import org.openmrs.Obs;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.NavUtils;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import de.uni_koblenz_landau.apow.db.ConceptAdapter;
import de.uni_koblenz_landau.apow.dialogs.DeleteDialogFragment;
import de.uni_koblenz_landau.apow.dialogs.DeleteDialogListener;
import de.uni_koblenz_landau.apow.helper.Constants;
import de.uni_koblenz_landau.apow.helper.ListViewItem;
import de.uni_koblenz_landau.apow.tasks.FindingListInterface;
import de.uni_koblenz_landau.apow.tasks.FindingListTask;
import de.uni_koblenz_landau.apow.tasks.ObsDeleteTask;
import de.uni_koblenz_landau.apow.tasks.ObsDetailInterface;
import de.uni_koblenz_landau.apow.tasks.ObsDetailTask;
import de.uni_koblenz_landau.apow.tasks.DataUpdateInterface;
import de.uni_koblenz_landau.apow.tasks.ObsUpdateTask;
import de.uni_koblenz_landau.apow.tasks.SettingsUpdateTask;
import de.uni_koblenz_landau.apow.tasks.SymptomListInterface;
import de.uni_koblenz_landau.apow.tasks.SymptomListTask;
import de.uni_koblenz_landau.apow.tasks.TaskActivity;
import de.uni_koblenz_landau.apow.tasks.TaskActivityReference;

/**
 * Fragment for showing an updating an observation.
 * 
 * @author Martin Landua
 * 
 */
public class ObsDetailFragment extends Fragment implements ObsDetailInterface, DataUpdateInterface,
        FindingListInterface, SymptomListInterface, TaskActivity, DeleteDialogListener {

    // Constants
    public static final String ARG_OBS_ID = "obs_id";
    private static final String ARG_OBS = "obs";
    public static final String ARG_TESTS = "tests";
    public static final String ARG_ENCOUNTER_ID = "encounter_id";
    public static final String ARG_TITLE = "title";
    private static final String ARG_FINDING_CODE = "finding_code";
    private static final String ARG_SYMPTOM_CODE = "symptom_code";
    private static final String ARG_TEST_CONCEPTS = "test_concepts";
    private static final String DELETE_DIALOG_ID = "deletedialog";
    private static final int KEY_QUESTION = 0;
    private static final int KEY_TEST = 1;
    private static final int KEY_FINDING = 2;
    private static final int KEY_SYMPTOM = 3;

    // Tasks
    private FindingListTask mFindingListTask;
    private ObsDeleteTask mObsDeleteTask;
    private ObsDetailTask mObsDetailTask;
    private ObsUpdateTask mObsUpdateTask;
    private SymptomListTask mSymptomListTask;

    // UI Variables
    private int mEncounterID;
    private Obs mObs;
    private int mObsID;
    private String mQuestionText;
    private String mTestValue;
    private List<ListViewItem> mTestConcepts;
    private int findingCode;
    private Boolean findingCodeBlock = true;
    private int symptomCode;
    private Boolean symptomCodeBlock = true;

    // UI references
    private DeleteDialogFragment mDeleteDialog;
    private LinearLayout mClassLayout;
    private Spinner mClassSpinner;
    private LinearLayout mQuestionLayout;
    private EditText mQuestionTextView;
    private LinearLayout mTestLayout;
    private EditText mTestValueView;
    private Spinner mTestConceptView;
    private TextView mTestUnitView;
    private LinearLayout mFindingLayout;
    private AutoCompleteTextView mFindingValueCodedView;
    private CheckBox mFindingCertaintyView;
    private CheckBox mFindingSeverityCodedView;
    private LinearLayout mSymptomLayout;
    private AutoCompleteTextView mSymptomValueView;

    /**
     * Empty constructor for Instantiation
     */
    public ObsDetailFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        setHasOptionsMenu(true);
        getActivity().setTitle(getArguments().getString(ARG_TITLE));
        super.onCreate(savedInstanceState);

        // Re-attach Tasks.
        TaskActivityReference.getInstance().attach(FindingListTask.TASK_ID, this);
        TaskActivityReference.getInstance().attach(ObsDeleteTask.TASK_ID, this);
        TaskActivityReference.getInstance().attach(ObsDetailTask.TASK_ID, this);
        TaskActivityReference.getInstance().attach(ObsUpdateTask.TASK_ID, this);
        TaskActivityReference.getInstance().attach(SymptomListTask.TASK_ID, this);

        if (getArguments().containsKey(ARG_ENCOUNTER_ID)) {
            mEncounterID = getArguments().getInt(ARG_ENCOUNTER_ID);
        }

        if (getArguments().containsKey(ARG_OBS_ID)) {
            mObsID = getArguments().getInt(ARG_OBS_ID);
        }

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.obs_detail_fragment, container, false);

        // Create UI references.
        mDeleteDialog = (DeleteDialogFragment) getFragmentManager().findFragmentByTag(DELETE_DIALOG_ID);
        if (mDeleteDialog != null) {
            mDeleteDialog.setListener(this);
        }
        mClassLayout = (LinearLayout) view.findViewById(R.id.obs_detail_class);
        mClassSpinner = (Spinner) view.findViewById(R.id.obs_detail_class_spinner);
        mClassSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View v, int pos, long id) {

                mQuestionLayout.setVisibility(View.GONE);
                mTestLayout.setVisibility(View.GONE);
                mFindingLayout.setVisibility(View.GONE);
                mSymptomLayout.setVisibility(View.GONE);

                switch (pos) {
                case Constants.CLASS_QUESTION:
                    mQuestionLayout.setVisibility(View.VISIBLE);
                    break;
                case Constants.CLASS_TEST:
                    mTestLayout.setVisibility(View.VISIBLE);
                    break;
                case Constants.CLASS_FINDING:
                    mFindingLayout.setVisibility(View.VISIBLE);
                    break;
                case Constants.CLASS_SYMPTOM:
                    mSymptomLayout.setVisibility(View.VISIBLE);
                    break;
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });
        mQuestionLayout = (LinearLayout) view.findViewById(R.id.obs_detail_question);
        mQuestionTextView = (EditText) view.findViewById(R.id.obs_detail_question_text);
        mTestLayout = (LinearLayout) view.findViewById(R.id.obs_detail_test);
        mTestConceptView = (Spinner) view.findViewById(R.id.obs_detail_test_concept);
        mTestConceptView.setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View v, int pos, long id) {
                ListViewItem item = (ListViewItem) parent.getItemAtPosition(pos);
                mTestUnitView.setText(item.getField2());
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });
        mTestUnitView = (TextView) view.findViewById(R.id.obs_detail_test_unit);
        mTestValueView = (EditText) view.findViewById(R.id.obs_detail_test_value);
        mFindingLayout = (LinearLayout) view.findViewById(R.id.obs_detail_finding);
        mFindingValueCodedView = (AutoCompleteTextView) view.findViewById(R.id.obs_detail_finding_value_coded);
        mFindingValueCodedView.addTextChangedListener(new TextWatcher() {

            @Override
            public void afterTextChanged(Editable s) {
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (!findingCodeBlock) {
                    findingCode = -1;
                }
                findingCodeBlock = false;
                searchFindings(s.toString().trim());
            }
        });

        mFindingValueCodedView.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> listView, View view, int position, long id) {
                findingCode = (int) id;
            }
        });
        mFindingCertaintyView = (CheckBox) view.findViewById(R.id.obs_detail_finding_certainty);
        mFindingSeverityCodedView = (CheckBox) view.findViewById(R.id.obs_detail_finding_severity_coded);
        mSymptomLayout = (LinearLayout) view.findViewById(R.id.obs_detail_symptom);
        mSymptomValueView = (AutoCompleteTextView) view.findViewById(R.id.obs_detail_symptom_value);
        mSymptomValueView.addTextChangedListener(new TextWatcher() {

            @Override
            public void afterTextChanged(Editable s) {
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (!symptomCodeBlock) {
                    symptomCode = -1;
                }
                symptomCodeBlock = false;
                searchSymptoms(s.toString().trim());
            }
        });
        mSymptomValueView.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> listView, View view, int position, long id) {
                symptomCode = (int) id;
            }
        });

        // Restore UI from saved instance or load data.
        if (savedInstanceState != null) {
            findingCode = savedInstanceState.getInt(ARG_FINDING_CODE);
            symptomCode = savedInstanceState.getInt(ARG_SYMPTOM_CODE);

            mObs = (Obs) savedInstanceState.getSerializable(ARG_OBS);
            if (mObs != null) {
                mTestConcepts = savedInstanceState.getParcelableArrayList(ARG_TEST_CONCEPTS);

                ArrayAdapter<ListViewItem> adapter = new ArrayAdapter<>(getActivity(),
                        android.R.layout.simple_spinner_item, mTestConcepts);
                adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                mTestConceptView.setAdapter(adapter);
                restoreView();
            }
        } else {
            findingCode = -1;
            symptomCode = -1;
            loadObs();
        }
        return view;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // Detach tasks for preventing memory leaks.
        TaskActivityReference.getInstance().detach(FindingListTask.TASK_ID);
        TaskActivityReference.getInstance().detach(ObsDeleteTask.TASK_ID);
        TaskActivityReference.getInstance().detach(ObsDetailTask.TASK_ID);
        TaskActivityReference.getInstance().detach(ObsUpdateTask.TASK_ID);
        TaskActivityReference.getInstance().detach(SymptomListTask.TASK_ID);
    }

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        savedInstanceState.putInt(ARG_FINDING_CODE, findingCode);
        savedInstanceState.putInt(ARG_SYMPTOM_CODE, symptomCode);
        savedInstanceState.putSerializable(ARG_OBS, mObs);
        savedInstanceState.putParcelableArrayList(ARG_TEST_CONCEPTS, (ArrayList<ListViewItem>) mTestConcepts);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.obs_detail, menu);
        // If new observation, hide delete button.
        if (getArguments().containsKey(ARG_OBS_ID) && getArguments().getInt(ARG_OBS_ID) != -1) {
            menu.findItem(R.id.obs_detail_action_discard).setVisible(true);
        }

        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == android.R.id.home) {
            NavUtils.navigateUpFromSameTask(getActivity());
            return true;
        }

        if (id == R.id.obs_detail_action_discard) {
            mDeleteDialog = DeleteDialogFragment.newInstance(R.string.obs_detail_delete_dialog_title);
            mDeleteDialog.setListener(this);
            mDeleteDialog.show(getActivity().getSupportFragmentManager(), DELETE_DIALOG_ID);
            return true;
        }
        if (id == R.id.obs_detail_action_save) {
            save();
            return true;
        }
        if (id == R.id.obs_detail_action_cancel) {
            Intent back = new Intent(getActivity(), ObsListActivity.class);
            NavUtils.navigateUpTo(getActivity(), back);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * Checks input and saves settings to database.
     */
    public void save() {
        // Abort if task is already running.
        if (mObsUpdateTask != null) {
            return;
        }

        // Reset errors.
        mQuestionTextView.setError(null);
        mTestValueView.setError(null);
        mFindingValueCodedView.setError(null);
        mSymptomValueView.setError(null);

        // Store UI values.
        mQuestionText = mQuestionTextView.getText().toString().trim();
        mTestValue = mTestValueView.getText().toString().trim();

        // Find observation type.
        int type = -1;

        // Observation is question.
        if ((mObs.getConcept() != null && mObs.getConcept().getConceptId() == Constants.QUESTION_CONCEPT_ID)
                || (mObs.getConcept() == null
                        && mClassSpinner.getSelectedItemPosition() == Constants.CLASS_QUESTION)) {
            type = KEY_QUESTION;
            // Observation is test.
        } else if ((mObs.getConcept() != null && mObs.getConcept().getConceptClass() != null
                && mObs.getConcept().getConceptClass().getConceptClassId() == Constants.TEST_CLASS_ID)
                || (mObs.getConcept() == null && mClassSpinner.getSelectedItemPosition() == Constants.CLASS_TEST)) {
            type = KEY_TEST;
            // Observation is finding.
        } else if ((mObs.getConcept() != null
                && mObs.getConcept().getConceptId() == Constants.FINDING_SET_CONCEPT_ID)
                || (mObs.getConcept() == null
                        && mClassSpinner.getSelectedItemPosition() == Constants.CLASS_FINDING)) {
            type = KEY_FINDING;
            // Observation is symptom.
        } else if ((mObs.getConcept() != null && mObs.getConcept().getConceptClass() != null
                && mObs.getConcept().getConceptClass().getConceptClassId() == Constants.SYMPTOM_CONCEPT_CLASS_ID)
                || (mObs.getConcept() == null
                        && mClassSpinner.getSelectedItemPosition() == Constants.CLASS_SYMPTOM)) {
            type = KEY_SYMPTOM;
        }

        Boolean cancel = false;
        View focusView = null;

        // Validate UI input.

        Double mTestValueDouble = null;
        if (type == KEY_QUESTION) {
            if (TextUtils.isEmpty(mQuestionText)) {
                mQuestionTextView.setError(getString(R.string.error_field_required));
                focusView = mQuestionTextView;
                cancel = true;
            }
        } else if (type == KEY_TEST) {
            if (TextUtils.isEmpty(mTestValue)) {
                mTestValueView.setError(getString(R.string.error_field_required));
                focusView = mTestValueView;
                cancel = true;
            } else {
                try {
                    mTestValueDouble = Double.parseDouble(mTestValue);
                    Double low = ((ListViewItem) mTestConceptView.getSelectedItem()).getValue1();
                    Double hi = ((ListViewItem) mTestConceptView.getSelectedItem()).getValue2();
                    if (low != -1 && hi != -1 && (mTestValueDouble < low || mTestValueDouble > hi)) {
                        mTestValueView.setError(getActivity().getString(R.string.error_field_out_of_range) + " ["
                                + low + "," + hi + "]");
                        focusView = mTestValueView;
                        cancel = true;
                    }
                } catch (NumberFormatException nfe) {
                    mTestValueView.setError(getActivity().getString(R.string.error_field_not_numeric));
                    focusView = mTestValueView;
                    cancel = true;
                }
            }
        } else if (type == KEY_FINDING) {
            if (findingCode == -1) {
                mFindingValueCodedView.setError(getActivity().getString(R.string.error_field_not_from_list));
                focusView = mTestValueView;
                cancel = true;
            }
        } else if (type == KEY_SYMPTOM) {
            if (symptomCode == -1) {
                mSymptomValueView.setError(getActivity().getString(R.string.error_field_not_from_list));
                focusView = mTestValueView;
                cancel = true;
            }
        }

        // If there are errors cancel, else save to database.
        if (cancel) {
            focusView.requestFocus();
        } else {
            // Update obs object
            if (type == KEY_QUESTION) {
                mObs.setConcept(new Concept(Constants.QUESTION_CONCEPT_ID));
                mObs.setValueText(mQuestionText);
            } else if (type == KEY_TEST) {
                ConceptNumeric concept = new ConceptNumeric(
                        ((ListViewItem) mTestConceptView.getSelectedItem()).getId());
                ConceptDatatype datatype = new ConceptDatatype();
                datatype.setName(Constants.CONCEPT_DATATYPE_NUMERIC);
                concept.setDatatype(datatype);
                mObs.setConcept(concept);
                mObs.setValueNumeric(mTestValueDouble);
            } else if (type == KEY_FINDING) {
                if (mObs.hasGroupMembers()) {
                    for (Obs obs : mObs.getGroupMembers()) {
                        if (obs.getConcept().getConceptId() == Constants.FINDING_CONCEPT) {
                            if (findingCode != -1) {
                                obs.setValueCoded(new Concept(findingCode));
                            }
                        }
                        if (obs.getConcept().getConceptId() == Constants.FINDING_CERTAINTY) {
                            if (mFindingCertaintyView.isChecked()) {
                                obs.setValueCoded(new Concept(Constants.FINDING_CERTAINTY_CONFIRMED));
                            } else {
                                obs.setValueCoded(new Concept(Constants.FINDING_CERTAINTY_NOT_CONFIRMED));
                            }
                        }
                        if (obs.getConcept().getConceptId() == Constants.FINDING_SEVERITY) {
                            if (mFindingSeverityCodedView.isChecked()) {
                                obs.setValueCoded(new Concept(Constants.FINDING_SEVERITY_PRIMARY));
                            } else {
                                obs.setValueCoded(new Concept(Constants.FINDING_SEVERITY_SECONDARY));
                            }
                        }
                    }
                } else {
                    mObs.setConcept(new Concept(Constants.FINDING_SET_CONCEPT_ID));

                    Obs concept = new Obs();
                    concept.setConcept(new Concept(Constants.FINDING_CONCEPT));
                    concept.setValueCoded(new Concept(findingCode));
                    mObs.addGroupMember(concept);

                    Obs certainty = new Obs();
                    certainty.setConcept(new Concept(Constants.FINDING_CERTAINTY));
                    if (mFindingCertaintyView.isChecked()) {
                        certainty.setValueCoded(new Concept(Constants.FINDING_CERTAINTY_CONFIRMED));
                    } else {
                        certainty.setValueCoded(new Concept(Constants.FINDING_CERTAINTY_NOT_CONFIRMED));
                    }
                    mObs.addGroupMember(certainty);

                    Obs severity = new Obs();
                    severity.setConcept(new Concept(Constants.FINDING_SEVERITY));
                    if (mFindingSeverityCodedView.isChecked()) {
                        severity.setValueCoded(new Concept(Constants.FINDING_SEVERITY_PRIMARY));
                    } else {
                        severity.setValueCoded(new Concept(Constants.FINDING_SEVERITY_SECONDARY));
                    }
                    mObs.addGroupMember(severity);
                }
            } else if (type == KEY_SYMPTOM) {
                mObs.setConcept(new Concept(symptomCode));
            }

            // Start update task.
            mObsUpdateTask = new ObsUpdateTask();
            TaskActivityReference.getInstance().addTask(SettingsUpdateTask.TASK_ID, mObsUpdateTask, this);
            mObsUpdateTask.execute(mObs);
        }
    }

    /**
     * Called by update task, when update is finished.
     */
    @Override
    public void onDataUpdateFinished() {
        mObsUpdateTask = null;

        // Leave activity.
        Intent intent = new Intent(getActivity(), ObsListActivity.class);
        NavUtils.navigateUpTo(getActivity(), intent);
    }

    /**
     * Starts task to load settings.
     */
    private void loadObs() {
        // Abort if task is already running.
        if (mObsDetailTask != null) {
            return;
        }

        // Start detail task.
        mObsDetailTask = new ObsDetailTask();
        TaskActivityReference.getInstance().addTask(ObsDetailTask.TASK_ID, mObsDetailTask, this);
        mObsDetailTask.execute(mObsID);
    }

    /**
     * Called by settings task, when loading is finished.
     */
    @Override
    public void onObsFetched(Obs obs, List<ListViewItem> testConcepts) {
        mObsDetailTask = null;

        // If result is not empty, update UI, else show error message.
        if (testConcepts != null) {
            mTestConcepts = testConcepts;
            ArrayAdapter<ListViewItem> adapter = new ArrayAdapter<>(getActivity(),
                    android.R.layout.simple_spinner_item, mTestConcepts);
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            mTestConceptView.setAdapter(adapter);

            if (obs != null) {
                mObs = obs;

                // Observation is question.
                if (mObs.getConcept().getConceptId() == Constants.QUESTION_CONCEPT_ID) {
                    mQuestionTextView.setText(mObs.getValueText());
                    // Observation is test.
                } else if (mObs.getConcept().getConceptClass().getConceptClassId() == Constants.TEST_CLASS_ID) {
                    mTestValueView.setText("" + mObs.getValueNumeric());
                    mTestUnitView.setText(((ConceptNumeric) mObs.getConcept()).getUnits());

                    int position = -1;
                    for (int i = 0; i < adapter.getCount(); i++) {
                        if (adapter.getItem(i).getId() == mObs.getConcept().getConceptId()) {
                            position = i;
                            break;
                        }
                    }
                    mTestConceptView.setSelection(position);

                    // Observation is finding.
                } else if (mObs.getConcept().getConceptId() == Constants.FINDING_SET_CONCEPT_ID) {
                    for (Obs obs1 : mObs.getGroupMembers()) {
                        if (obs1.getConcept().getConceptId() == Constants.FINDING_CONCEPT) {
                            mFindingValueCodedView.setText(obs1.getValueCoded().getName().getName());
                            findingCode = obs1.getValueCoded().getConceptId();
                        }
                        if (obs1.getConcept().getConceptId() == Constants.FINDING_CERTAINTY
                                && obs1.getValueCoded().getConceptId() == Constants.FINDING_CERTAINTY_CONFIRMED) {
                            mFindingCertaintyView.setChecked(true);
                        }
                        if (obs1.getConcept().getConceptId() == Constants.FINDING_SEVERITY
                                && obs1.getValueCoded().getConceptId() == Constants.FINDING_SEVERITY_PRIMARY) {
                            mFindingSeverityCodedView.setChecked(true);
                        }
                    }
                    // Observation is symptom.
                } else if (mObs.getConcept().getConceptClass()
                        .getConceptClassId() == Constants.SYMPTOM_CONCEPT_CLASS_ID) {
                    mSymptomValueView.setText(mObs.getConcept().getName().getName());
                    symptomCode = mObs.getConcept().getConceptId();
                }
            } else {
                mObs = new Obs();
                mObs.setEncounter(new Encounter(mEncounterID));
            }
            restoreView();
        } else {
            Toast.makeText(getActivity(), R.string.error_database, Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * Initialize views.
     */
    public void restoreView() {
        if (mObs != null) {
            if (mObs.getId() == null) {
                mClassLayout.setVisibility(View.VISIBLE);
            } else {
                // Observation is question.
                if (mObs.getConcept().getConceptId() == Constants.QUESTION_CONCEPT_ID) {
                    mQuestionLayout.setVisibility(View.VISIBLE);
                }
                // Observation is test.
                if (mObs.getConcept().getConceptClass().getConceptClassId() == Constants.TEST_CLASS_ID) {
                    mTestLayout.setVisibility(View.VISIBLE);
                }
                // Observation is finding.
                if (mObs.getConcept().getConceptId() == Constants.FINDING_SET_CONCEPT_ID) {
                    mFindingLayout.setVisibility(View.VISIBLE);
                }
                // Observation is symptom.
                if (mObs.getConcept().getConceptClass().getConceptClassId() == Constants.SYMPTOM_CONCEPT_CLASS_ID) {
                    mSymptomLayout.setVisibility(View.VISIBLE);
                }
            }
        }
    }

    /**
     * Starts task to find findings.
     * 
     * @param search Search query
     */
    private void searchFindings(String search) {
        // Abort if task is already running.
        if (mFindingListTask != null) {
            return;
        }

        // Start task.
        mFindingListTask = new FindingListTask();
        TaskActivityReference.getInstance().addTask(FindingListTask.TASK_ID, mFindingListTask, this);
        mFindingListTask.execute(search);
    }

    /**
     * Called by findings task, when loading is finished.
     */
    @Override
    public void onFindingsFetched(List<Concept> concepts) {
        mFindingListTask = null;

        // If result is not empty, update UI, else show error message.
        if (concepts != null) {
            ConceptAdapter adapter = new ConceptAdapter(getActivity(), concepts);
            mFindingValueCodedView.setAdapter(adapter);
        } else {
            Toast.makeText(getActivity(), R.string.error_database, Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * Starts task to find symptoms.
     * 
     * @param search Search query
     */
    private void searchSymptoms(String search) {
        // Abort if task is already running.
        if (mSymptomListTask != null) {
            return;
        }

        // Start task.
        mSymptomListTask = new SymptomListTask();
        TaskActivityReference.getInstance().addTask(SymptomListTask.TASK_ID, mSymptomListTask, this);
        mSymptomListTask.execute(search);
    }

    /**
     * Called by symptoms task, when loading is finished.
     */
    @Override
    public void onSymptomsFetched(List<Concept> concepts) {
        mSymptomListTask = null;

        // If result is not empty, update UI, else show error message.
        if (concepts != null) {
            ConceptAdapter adapter = new ConceptAdapter(getActivity(), concepts);
            mSymptomValueView.setAdapter(adapter);
        } else {
            Toast.makeText(getActivity(), R.string.error_database, Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * Callback for delete dialog.
     */
    @Override
    public void deleteItem(String voidReason) {
        // Abort if task is already running.
        if (mObsDeleteTask != null) {
            return;
        }

        // Start task.
        mObsDeleteTask = new ObsDeleteTask(mObsID, mObs.hasGroupMembers(), voidReason);
        TaskActivityReference.getInstance().addTask(ObsDeleteTask.TASK_ID, mObsDeleteTask, this);
        mObsDeleteTask.execute();
    }
}