org.eyeseetea.malariacare.fragments.CreateSurveyFragment.java Source code

Java tutorial

Introduction

Here is the source code for org.eyeseetea.malariacare.fragments.CreateSurveyFragment.java

Source

/*
 * Copyright (c) 2015.
 *
 * This file is part of Facility QA Tool App.
 *
 *  Facility QA Tool App 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.
 *
 *  Facility QA Tool App 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.eyeseetea.malariacare.fragments;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.LinearLayout;
import android.widget.Spinner;

import org.eyeseetea.malariacare.DashboardActivity;
import org.eyeseetea.malariacare.R;
import org.eyeseetea.malariacare.database.model.OrgUnit;
import org.eyeseetea.malariacare.database.model.OrgUnitLevel;
import org.eyeseetea.malariacare.database.model.Program;
import org.eyeseetea.malariacare.database.model.Survey;
import org.eyeseetea.malariacare.database.utils.PreferencesState;
import org.eyeseetea.malariacare.database.utils.Session;
import org.eyeseetea.malariacare.layout.adapters.general.OrgUnitArrayAdapter;
import org.eyeseetea.malariacare.layout.adapters.general.ProgramArrayAdapter;
import org.eyeseetea.malariacare.services.SurveyService;
import org.eyeseetea.malariacare.utils.Constants;
import org.eyeseetea.malariacare.views.CustomButton;
import org.eyeseetea.malariacare.views.CustomTextView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by ignac on 05/01/2016.
 */
public class CreateSurveyFragment extends Fragment {

    private static String TAG = ".CreateSurveyFragment";

    // UI references.
    private Spinner orgUnitView;
    private View orgUnitContainerItems;
    private String TOKEN = ";";
    private String orgUnitStorage = "";

    public void init() {
        loadHierarchy = true;
    }

    static class ViewHolder {
        public View component;
    }

    private LinkedHashMap<OrgUnitLevel, View> orgUnitHierarchyView;

    private SurveyReceiver surveyReceiver;

    private Spinner programView;

    //Loaded one time from service
    List<Program> allProgramList;
    List<OrgUnit> orgUnitList;
    List<OrgUnitLevel> orgUnitLevelList;

    private OrgUnit orgUnitDefaultOption;
    private Program programDefaultOption;

    private OrgUnitHierarchy orgUnitHierarchy;

    private LayoutInflater lInflater;
    LinearLayout llLayout;

    DashboardActivity dashboardActivity;

    //Flag used to control the layout inflating is only in the creation of the fragment.
    private boolean loadHierarchy = true;

    public CreateSurveyFragment() {
    }

    public static CreateSurveyFragment newInstance(int index) {
        CreateSurveyFragment f = new CreateSurveyFragment();

        // Supply index input as an argument.
        Bundle args = new Bundle();
        args.putInt("index", index);
        f.setArguments(args);

        return f;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "onCreate");
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onStop() {
        Log.d(TAG, "onStop");
        unregisterReceiver();

        super.onStop();
    }

    @Override
    public void onPause() {
        Log.d(TAG, "onPause");
        unregisterReceiver();

        super.onPause();
    }

    @Override
    public void onResume() {
        Log.d(TAG, "onResume");
        registerReceiver();
        super.onResume();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView");
        init();
        if (container == null) {
            return null;
        }
        llLayout = (LinearLayout) inflater.inflate(R.layout.create_survey_fragment, container, false);
        registerReceiver();
        getData();
        return llLayout; // We must return the loaded Layout
    }

    public void getData() {
        //get data using service
        Intent surveysIntent = new Intent(PreferencesState.getInstance().getContext().getApplicationContext(),
                SurveyService.class);
        surveysIntent.putExtra(SurveyService.SERVICE_METHOD, SurveyService.ALL_CREATE_SURVEY_DATA_ACTION);
        PreferencesState.getInstance().getContext().getApplicationContext().startService(surveysIntent);
    }

    public void create() {
        orgUnitHierarchy = new OrgUnitHierarchy();
        CustomButton createButton = (CustomButton) llLayout.findViewById(R.id.create_form_button);
        createButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //If the survey is validate, it send the order of create survey fragment from this fragment to the activity.
                if (validateForm()) {
                    createSurvey();
                }
            }
        });
        this.lInflater = LayoutInflater.from(getActivity());

        //Create default options
        orgUnitDefaultOption = new OrgUnit(Constants.DEFAULT_SELECT_OPTION);
        programDefaultOption = new Program(Constants.DEFAULT_SELECT_OPTION);

        //Populate Organization Unit DDL
        ViewHolder viewHolder = new ViewHolder();
        List<OrgUnit> orgUnitListFirstLevel = new ArrayList<>();
        for (OrgUnit orgUnit : orgUnitList) {
            if (orgUnitList.get(0).getOrgUnitLevel() == orgUnit.getOrgUnitLevel()) {
                orgUnitListFirstLevel.add(orgUnit);
            }
        }
        orgUnitListFirstLevel.add(0, orgUnitDefaultOption);
        viewHolder.component = llLayout.findViewById(R.id.org_unit);
        orgUnitView = (Spinner) viewHolder.component;
        orgUnitView.setTag(orgUnitListFirstLevel.get(1).getOrgUnitLevel());
        orgUnitView.setAdapter(new OrgUnitArrayAdapter(getActivity(), orgUnitListFirstLevel));
        orgUnitView.setOnItemSelectedListener(new OrgUnitSpinnerListener(viewHolder));

        View childView = llLayout.findViewById(R.id.org_unit_container);
        CustomTextView childViewTextView = (CustomTextView) childView.findViewById(R.id.textView2);
        childViewTextView.setText(orgUnitListFirstLevel.get(1).getOrgUnitLevel().getName());

        //Put in org unit hierarchy map
        orgUnitHierarchyView = new LinkedHashMap<>();
        orgUnitHierarchyView.put(orgUnitListFirstLevel.get(1).getOrgUnitLevel(), childView);

        //Prepare Organization Unit Item DDL
        orgUnitContainerItems = llLayout.findViewById(R.id.org_unit_container_items);

        for (OrgUnitLevel orgUnitLevel : orgUnitLevelList) {
            if (!orgUnitLevel.equals(orgUnitListFirstLevel.get(1).getOrgUnitLevel())) {
                childView = lInflater.inflate(R.layout.create_survey_org_unit_item_fragment,
                        (LinearLayout) orgUnitContainerItems, false);
                childViewTextView = (CustomTextView) childView.findViewById(R.id.textView);
                childViewTextView.setText(orgUnitLevel.getName());

                Spinner childViewSpinner = (Spinner) childView.findViewById(R.id.org_unit_item_spinner);
                childViewSpinner.setTag(orgUnitLevel);
                childView.setVisibility(View.GONE);
                ((LinearLayout) orgUnitContainerItems).addView(childView);
                //Put in org unit hierarchy map
                orgUnitHierarchyView.put(orgUnitLevel, childView);
            }
        }

        //Populate Program View DDL
        //get all the programs from a DB query only one time.
        List<Program> initProgram = new ArrayList<>();
        initProgram.add(0, programDefaultOption);
        programView = (Spinner) llLayout.findViewById(R.id.program);
        programView.setAdapter(new ProgramArrayAdapter(getActivity(), initProgram));

        //set the first orgUnit saved
        orgUnitStorage = orgUnitHierarchy.getSavedUidsList().split(TOKEN)[0];

        //Load the root lastorgUnit/firstOrgUnit(if we have orgUnitLevels).
        if (!orgUnitStorage.equals("")) {
            orgUnitView.setSelection(getIndex(orgUnitView, OrgUnit.getOrgUnit(orgUnitStorage).getName()));
        }
        loadHierarchy = false;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        dashboardActivity = (DashboardActivity) activity;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        Log.d(TAG, "onActivityCreated");
        super.onActivityCreated(savedInstanceState);

    }

    //select the default item.
    private int getIndex(Spinner spinner, String myString) {
        int index = 0;
        for (int i = 0; i < spinner.getCount(); i++) {
            Object objectRow = spinner.getItemAtPosition(i);
            String value = "";
            if (objectRow instanceof Program) {
                value = ((Program) objectRow).getName();
            }
            if (objectRow instanceof OrgUnit) {
                value = ((OrgUnit) objectRow).getName();
            }
            if (value.equalsIgnoreCase(myString)) {
                index = i;
                break;
            }
        }
        return index;
    }

    private boolean isEverythingFilled() {
        try {
            boolean isEverythingFilled = (!programView.getSelectedItem().equals(programDefaultOption));
            boolean isProgramInOrgUnit = orgUnitHierarchy.getLastSelected().getPrograms()
                    .contains((Program) programView.getSelectedItem());
            return isEverythingFilled && isProgramInOrgUnit;
        } catch (NullPointerException ex) {
            return false;
        }
    }

    private boolean doesSurveyInProgressExist() {
        // Read Selected Items
        OrgUnit orgUnit = orgUnitHierarchy.getLastSelected();
        Program program = (Program) programView.getSelectedItem();

        Survey survey = Survey.getInProgressSurveys(orgUnit, program);
        return (survey != null);
    }

    private boolean validateForm() {
        if (!isEverythingFilled()) {
            new AlertDialog.Builder(getActivity())
                    .setTitle(getActivity().getApplicationContext()
                            .getString(R.string.dialog_title_missing_selection))
                    .setMessage(getActivity().getApplicationContext()
                            .getString(R.string.dialog_content_missing_selection))
                    .setPositiveButton(android.R.string.ok, null).create().show();
        } else if (!orgUnitHierarchy.getLastSelected().getPrograms()
                .contains((Program) programView.getSelectedItem())) {
            new AlertDialog.Builder(getActivity())
                    .setTitle(getActivity().getApplicationContext()
                            .getString(R.string.dialog_title_incorrect_org_unit))
                    .setMessage(getActivity().getApplicationContext()
                            .getString(R.string.dialog_content_incorrect_org_unit))
                    .setPositiveButton(android.R.string.ok, null).create().show();
        } else if (doesSurveyInProgressExist()) {
            new AlertDialog.Builder(getActivity())
                    .setTitle(
                            getActivity().getApplicationContext().getString(R.string.dialog_title_existing_survey))
                    .setMessage(getActivity().getApplicationContext()
                            .getString(R.string.dialog_content_existing_survey))
                    .setPositiveButton(android.R.string.ok, null).create().show();
        } else {
            return true;
        }

        return false;
    }

    /**
     * Called when the user clicks the Send button
     * Gets the survey with the SURVEY_PLANNED state and set the createdate, user, SURVEY_IN_PROGRESS, and reset main score, and save the survey in session
     */
    public void createSurvey() {
        Log.i(".CreateSurveyActivity", "Saving survey and saving in session");

        //Get selected orgUnit
        OrgUnit orgUnit = orgUnitHierarchy.getLastSelected();

        //Get selected program
        Program program = (Program) programView.getSelectedItem();

        //save  the list of orgUnits
        orgUnitHierarchy.saveSelectionInPreferences();

        //save the program in the preferents
        setLastSelectedProgram(program.getUid());

        dashboardActivity.onCreateSurvey(orgUnit, program);
    }

    private class OrgUnitSpinnerListener implements AdapterView.OnItemSelectedListener {

        private ViewHolder viewHolder;

        public OrgUnitSpinnerListener(ViewHolder viewHolder) {
            this.viewHolder = viewHolder;
        }

        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {

            OrgUnit selectedOrgUnit = (OrgUnit) ((Spinner) viewHolder.component).getItemAtPosition(1);
            OrgUnitLevel selectedOrgUnitLevel = selectedOrgUnit.getOrgUnitLevel();
            selectedOrgUnit = (OrgUnit) ((Spinner) viewHolder.component).getItemAtPosition(pos);

            if (selectedOrgUnit.getUid() == null)
                selectedOrgUnit.setOrgUnitLevel(selectedOrgUnitLevel);

            // Populate child view. If it exists in org unit map, grab it; otherwise inflate it
            List<OrgUnit> orgUnitList = selectedOrgUnit.getChildrenOrderedByName();

            orgUnitHierarchy.addOrgUnit(selectedOrgUnit);
            if (orgUnitHierarchy.getLastSelected() != null)
                refreshPrograms(orgUnitHierarchy.getLastSelected());

            // If there are children create spinner or populate it otherwise hide existing one
            if (orgUnitList.size() > 0) {
                View childView;
                if (orgUnitList.get(0).getUid() != null) {
                    childView = orgUnitHierarchyView.get(orgUnitList.get(0).getOrgUnitLevel());
                } else {
                    childView = orgUnitHierarchyView.get(orgUnitList.get(1).getOrgUnitLevel());
                }
                if (childView == null || childView.findViewById(R.id.org_unit_item_spinner) == null) {
                    hideChild(false);
                } else {
                    ViewHolder subViewHolder = new ViewHolder();
                    subViewHolder.component = childView.findViewById(R.id.org_unit_item_spinner);

                    //Show  and populate orgunits spinner
                    if (orgUnitList.get(0).getUid() != null) {
                        orgUnitDefaultOption.setOrgUnitLevel(orgUnitList.get(0).getOrgUnitLevel());
                        orgUnitList.add(0, orgUnitDefaultOption);
                    }
                    Spinner spinner = ((Spinner) subViewHolder.component);
                    spinner.setAdapter(new OrgUnitArrayAdapter(getActivity(), orgUnitList));
                    spinner.setOnItemSelectedListener(new OrgUnitSpinnerListener(subViewHolder));

                    //Loads the saved org units and remove the list when the last was selected
                    orgUnitStorage = orgUnitHierarchy.getSavedUidsList();
                    if (!orgUnitStorage.equals("")) {
                        String[] list = orgUnitStorage.split(TOKEN);
                        String activeUid = "";
                        for (int i = 0; i < list.length; i++) {
                            if (!list[i].equals("") && !list[i].equals(TOKEN)) {
                                try {
                                    OrgUnit selectOrgUnit = OrgUnit.getOrgUnit(list[i]);
                                    int index = getIndex(spinner, selectOrgUnit.getName());
                                    if (index != 0) {
                                        activeUid = selectOrgUnit.getUid();
                                        spinner.setSelection(index, true);
                                    }
                                } catch (Exception e) {
                                }
                            }
                        }
                        if (!activeUid.equals("")) {
                            orgUnitHierarchy.removeUid(activeUid);
                        }
                        Log.d(TAG, orgUnitHierarchy.savedUidsList);
                    }

                    childView.setVisibility(View.VISIBLE);
                }
            } else {
                hideChild(false);
            }
        }

        private void hideChild(boolean click) {
            //If there is not any children, iterate over the org units spinners and hide non needed
            //FIXME This code is horrible. We need a more elegant way
            Boolean setInvisible = false;
            for (Map.Entry<OrgUnitLevel, View> entry : orgUnitHierarchyView.entrySet()) {
                if (setInvisible) {
                    View childView = entry.getValue();
                    ((Spinner) childView.findViewById(R.id.org_unit_item_spinner)).setSelection(0, click);
                    childView.setVisibility(View.GONE);
                }
                if (entry.getKey().equals((viewHolder.component).getTag())) {
                    setInvisible = true;
                }
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
    }

    //filter programs by orgUnit
    private void refreshPrograms(OrgUnit selectedOrgUnit) {
        if (filterPrograms(selectedOrgUnit).size() <= 1) {
            View view = llLayout.findViewById(R.id.select_survey_view);
            view.setVisibility(View.GONE);
        } else {
            View view = llLayout.findViewById(R.id.select_survey_view);
            view.setVisibility(View.VISIBLE);
        }
    }

    //filter programs by orgUnit
    private List<Program> filterPrograms(OrgUnit selectedOrgUnit) {

        List<Program> initProgram = new ArrayList<>();
        for (Program orgUnitProgram : selectedOrgUnit.getPrograms()) {
            for (Program program : allProgramList) {
                if (orgUnitProgram != null && orgUnitProgram.equals(program))
                    initProgram.add(orgUnitProgram);
            }
        }
        initProgram.add(0, programDefaultOption);
        programView = (Spinner) llLayout.findViewById(R.id.program);
        programView.setAdapter(new ProgramArrayAdapter(getActivity(), initProgram));
        Program lastSelectedProgram = getLastSelectedProgram();
        if (lastSelectedProgram != null) {
            programView.setSelection(getIndex(programView, lastSelectedProgram.getName()));
        }
        return initProgram;
    }

    private void saveOrgUnitList(String list) {
        SharedPreferences.Editor editor = getEditor();
        editor.putString(getString(R.string.default_orgUnits), list);
        editor.commit();
    }

    //Get the default orgUnitLevels
    private String getListOrgUnits() {
        SharedPreferences sharedPreferences = getSharedPreferences();
        return sharedPreferences.getString(
                getActivity().getApplicationContext().getResources().getString(R.string.default_orgUnits), "");
    }

    private SharedPreferences getSharedPreferences() {
        return PreferenceManager.getDefaultSharedPreferences(getActivity());
    }

    private SharedPreferences.Editor getEditor() {
        SharedPreferences sharedPreferences = getSharedPreferences();
        return sharedPreferences.edit();
    }

    //Gets the default program/
    private Program getLastSelectedProgram() {
        SharedPreferences sharedPreferences = getSharedPreferences();
        Program lastSelectedProgram = Program.getProgram(sharedPreferences.getString(
                getActivity().getApplicationContext().getResources().getString(R.string.default_program), ""));
        return lastSelectedProgram;
    }

    //Sets the default program
    private void setLastSelectedProgram(String uid) {
        SharedPreferences.Editor editor = getEditor();
        editor.putString(getString(R.string.default_program), uid);
        editor.commit();
    }

    /**
     * Register a survey receiver to load surveys into the listadapter
     */
    public void registerReceiver() {
        Log.d(TAG, "registerReceiver");

        if (surveyReceiver == null) {
            surveyReceiver = new SurveyReceiver();
            LocalBroadcastManager.getInstance(getActivity()).registerReceiver(surveyReceiver,
                    new IntentFilter(SurveyService.ALL_CREATE_SURVEY_DATA_ACTION));
        }
    }

    /**
     * Unregisters the survey receiver.
     * It really important to do this, otherwise each receiver will invoke its code.
     */
    public void unregisterReceiver() {
        Log.d(TAG, "unregisterReceiver");
        if (surveyReceiver != null) {
            LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(surveyReceiver);
            surveyReceiver = null;
        }
    }

    /**
     * Inner private class that receives the result from the service
     */
    private class SurveyReceiver extends BroadcastReceiver {
        private SurveyReceiver() {
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "onReceive");
            //Listening only intents from this method
            if (loadHierarchy)
                if (SurveyService.ALL_CREATE_SURVEY_DATA_ACTION.equals(intent.getAction())) {
                    HashMap<String, List> data = (HashMap<String, List>) Session
                            .popServiceValue(SurveyService.ALL_CREATE_SURVEY_DATA_ACTION);
                    orgUnitList = data.get(SurveyService.PREPARE_ORG_UNIT);
                    orgUnitLevelList = data.get(SurveyService.PREPARE_ORG_UNIT_LEVEL);
                    allProgramList = data.get(SurveyService.PREPARE_PROGRAMS);
                    create();
                }
        }
    }

    public class OrgUnitHierarchy {

        //Used to control the active selectedHierarchy
        List<OrgUnit> selectedHierarchy;

        //Used to restore the saved org unit list in preferences
        String savedUidsList;

        public OrgUnitHierarchy() {
            selectedHierarchy = new ArrayList<OrgUnit>();
            //get and set the lastOrgUnit list from Preferences
            setLastOrgUnitStringList();
        }

        public String getSavedUidsList() {
            return savedUidsList;
        }

        //Add the last valid org unit and remove the unselected levels
        public void addOrgUnit(OrgUnit orgUnit) {
            for (int i = selectedHierarchy.size() - 1; i > 0; i--) {
                //Remove the next levels from the active org unit selected list.
                if (selectedHierarchy.get(i).getOrgUnitLevel().getId_org_unit_level() >= orgUnit.getOrgUnitLevel()
                        .getId_org_unit_level())
                    selectedHierarchy.remove(i);
            }
            //Save only the real org unit
            if (orgUnit.getUid() != null)
                selectedHierarchy.add(orgUnit);
        }

        //If the uid is the last uid, the list was removed
        public void removeUid(String uid) {
            if (!savedUidsList.contains(uid + TOKEN))
                savedUidsList = "";
        }

        //Saved the selectedHierarchy list in the preferences
        public String saveSelectionInPreferences() {
            String orgUnitList = "";
            for (OrgUnit orgUnit : selectedHierarchy) {
                orgUnitList += orgUnit.getUid() + TOKEN;
            }
            orgUnitList = orgUnitList.substring(0, orgUnitList.lastIndexOf(TOKEN));

            saveOrgUnitList(orgUnitList);
            return orgUnitList;
        }

        public void setLastOrgUnitStringList() {
            savedUidsList = getListOrgUnits();
        }

        //Return the first uid and remove from the list.
        public String getAndRemoveOrderedOrgUnitUid() {
            String[] list = savedUidsList.split(TOKEN);
            savedUidsList = savedUidsList.replace(list[0] + TOKEN, "");
            return list[0];
        }

        public OrgUnit getLastSelected() {
            if (selectedHierarchy.size() > 0)
                return selectedHierarchy.get(selectedHierarchy.size() - 1);
            else
                return null;
        }
    }
}