org.openmrs.mobile.activities.addeditpatient.AddEditPatientFragment.java Source code

Java tutorial

Introduction

Here is the source code for org.openmrs.mobile.activities.addeditpatient.AddEditPatientFragment.java

Source

/*
 * The contents of this file are subject to the OpenMRS Public License
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://license.openmrs.org
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * Copyright (C) OpenMRS, LLC.  All Rights Reserved.
 */

package org.openmrs.mobile.activities.addeditpatient;

import android.Manifest;
import android.app.Activity;
import android.app.DatePickerDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RadioGroup;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;

import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.openmrs.mobile.R;
import org.openmrs.mobile.activities.dialog.CustomFragmentDialog;
import org.openmrs.mobile.activities.patientdashboard.PatientDashboardActivity;
import org.openmrs.mobile.activities.patientdashboard.details.PatientPhotoActivity;
import org.openmrs.mobile.application.OpenMRSLogger;
import org.openmrs.mobile.bundle.CustomDialogBundle;
import org.openmrs.mobile.listeners.watcher.PatientBirthdateValidatorWatcher;
import org.openmrs.mobile.models.Patient;
import org.openmrs.mobile.models.Person;
import org.openmrs.mobile.models.PersonAddress;
import org.openmrs.mobile.models.PersonName;
import org.openmrs.mobile.utilities.ApplicationConstants;
import org.openmrs.mobile.utilities.DateUtils;
import org.openmrs.mobile.utilities.StringUtils;
import org.openmrs.mobile.utilities.ToastUtil;
import org.openmrs.mobile.utilities.ViewUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import permissions.dispatcher.NeedsPermission;
import permissions.dispatcher.OnNeverAskAgain;
import permissions.dispatcher.OnPermissionDenied;
import permissions.dispatcher.OnShowRationale;
import permissions.dispatcher.PermissionRequest;
import permissions.dispatcher.RuntimePermissions;

@RuntimePermissions
public class AddEditPatientFragment extends Fragment implements AddEditPatientContract.View {
    private AddEditPatientContract.Presenter mPresenter;

    private RelativeLayout relativeLayout;
    private LocalDate birthdate;
    private DateTime bdt;

    private EditText edfname;
    private EditText edmname;
    private EditText edlname;
    private EditText eddob;
    private EditText edyr;
    private EditText edmonth;
    private EditText edaddr1;
    private EditText edaddr2;
    private EditText edcity;
    private AutoCompleteTextView edstate;
    private AutoCompleteTextView edcountry;
    private EditText edpostal;

    private RadioGroup gen;
    private ProgressBar progressBar;

    private TextView fnameerror;
    private TextView lnameerror;
    private TextView doberror;
    private TextView gendererror;
    private TextView addrerror;
    private TextView countryerror;

    private Button submitConfirm;

    private String[] countries;
    private ImageView patientImageView;

    private FloatingActionButton capturePhoto;
    private Bitmap patientPhoto = null;
    private String patientName;
    private File output = null;
    private final static int IMAGE_REQUEST = 1;
    private OpenMRSLogger logger = new OpenMRSLogger();

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.fragment_patient_info, container, false);
        resolveViews(root);
        addSuggestionsToAutoCompleTextView();
        addListeners();
        fillFields(mPresenter.getPatientToUpdate());
        return root;
    }

    @Override
    public void setPresenter(AddEditPatientContract.Presenter presenter) {
        this.mPresenter = presenter;
    }

    @Override
    public boolean isActive() {
        return isAdded();
    }

    @Override
    public void finishPatientInfoActivity() {
        getActivity().finish();
    }

    @Override
    public void scrollToTop() {
        ScrollView scrollView = (ScrollView) this.getActivity().findViewById(R.id.scrollView);
        scrollView.smoothScrollTo(0, scrollView.getPaddingTop());
    }

    @Override
    public void setErrorsVisibility(boolean givenNameError, boolean familyNameError, boolean dayOfBirthError,
            boolean addressError, boolean countryError, boolean genderError) {
        if (givenNameError) {
            fnameerror.setVisibility(View.VISIBLE);
        } else {
            fnameerror.setVisibility(View.INVISIBLE);
        }

        if (familyNameError) {
            lnameerror.setVisibility(View.VISIBLE);
        } else {
            lnameerror.setVisibility(View.INVISIBLE);
        }

        if (dayOfBirthError) {
            doberror.setVisibility(View.VISIBLE);
        } else {
            doberror.setVisibility(View.GONE);
        }

        if (addressError) {
            addrerror.setVisibility(View.VISIBLE);
        } else {
            addrerror.setVisibility(View.GONE);
        }

        if (countryError) {
            countryerror.setVisibility(View.VISIBLE);
        } else {
            countryerror.setVisibility(View.GONE);
        }

        if (genderError) {
            gendererror.setVisibility(View.VISIBLE);
        } else {
            gendererror.setVisibility(View.GONE);
        }
    }

    private Person createPerson() {
        Person person = new Person();

        // Add address
        PersonAddress address = new PersonAddress();
        address.setAddress1(ViewUtils.getInput(edaddr1));
        address.setAddress2(ViewUtils.getInput(edaddr2));
        address.setCityVillage(ViewUtils.getInput(edcity));
        address.setPostalCode(ViewUtils.getInput(edpostal));
        address.setCountry(ViewUtils.getInput(edcountry));
        address.setStateProvince(ViewUtils.getInput(edstate));
        address.setPreferred(true);

        List<PersonAddress> addresses = new ArrayList<>();
        addresses.add(address);
        person.setAddresses(addresses);

        // Add names
        PersonName name = new PersonName();
        name.setFamilyName(ViewUtils.getInput(edlname));
        name.setGivenName(ViewUtils.getInput(edfname));
        name.setMiddleName(ViewUtils.getInput(edmname));

        List<PersonName> names = new ArrayList<>();
        names.add(name);
        person.setNames(names);

        // Add gender
        String[] genderChoices = { "M", "F" };
        int index = gen.indexOfChild(getActivity().findViewById(gen.getCheckedRadioButtonId()));
        if (index != -1) {
            person.setGender(genderChoices[index]);
        } else {
            person.setGender(null);
        }

        // Add birthdate
        String birthdate = null;
        DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(DateUtils.OPEN_MRS_REQUEST_PATIENT_FORMAT);
        if (ViewUtils.isEmpty(eddob)) {
            if (!StringUtils.isBlank(ViewUtils.getInput(edyr))
                    || !StringUtils.isBlank(ViewUtils.getInput(edmonth))) {
                int yeardiff = ViewUtils.isEmpty(edyr) ? 0 : Integer.parseInt(edyr.getText().toString());
                int mondiff = ViewUtils.isEmpty(edmonth) ? 0 : Integer.parseInt(edmonth.getText().toString());
                LocalDate now = new LocalDate();
                bdt = now.toDateTimeAtStartOfDay().toDateTime();
                bdt = bdt.minusYears(yeardiff);
                bdt = bdt.minusMonths(mondiff);
                person.setBirthdateEstimated(true);
                birthdate = dateTimeFormatter.print(bdt);
            }
        } else {
            birthdate = dateTimeFormatter.print(bdt);
        }
        person.setBirthdate(birthdate);

        if (patientPhoto != null)
            person.setPhoto(patientPhoto);

        return person;
    }

    private Patient createPatient() {
        final Patient patient = new Patient();
        patient.setPerson(createPerson());
        patient.setUuid(" ");
        return patient;
    }

    private Patient updatePatient(Patient patient) {
        patient.setPerson(createPerson());
        return patient;
    }

    @Override
    public void hideSoftKeys() {
        View view = this.getActivity().getCurrentFocus();
        if (view == null) {
            view = new View(this.getActivity());
        }
        InputMethodManager inputMethodManager = (InputMethodManager) this.getActivity()
                .getSystemService(Context.INPUT_METHOD_SERVICE);
        inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }

    @Override
    public void setProgressBarVisibility(boolean visibility) {
        progressBar.setVisibility(visibility ? View.VISIBLE : View.GONE);
    }

    @Override
    public void showSimilarPatientDialog(List<Patient> patients, Patient newPatient) {
        setProgressBarVisibility(false);
        CustomDialogBundle similarPatientsDialog = new CustomDialogBundle();
        similarPatientsDialog.setTitleViewMessage(getString(R.string.similar_patients_dialog_title));
        similarPatientsDialog.setRightButtonText(getString(R.string.dialog_button_register_new));
        similarPatientsDialog.setRightButtonAction(CustomFragmentDialog.OnClickAction.REGISTER_PATIENT);
        similarPatientsDialog.setLeftButtonText(getString(R.string.dialog_button_cancel));
        similarPatientsDialog.setLeftButtonAction(CustomFragmentDialog.OnClickAction.CANCEL_REGISTERING);
        similarPatientsDialog.setPatientsList(patients);
        similarPatientsDialog.setNewPatient(newPatient);
        ((AddEditPatientActivity) this.getActivity()).createAndShowDialog(similarPatientsDialog,
                ApplicationConstants.DialogTAG.SIMILAR_PATIENTS_TAG);
    }

    @Override
    public void startPatientDashbordActivity(Patient patient) {
        Intent intent = new Intent(getActivity(), PatientDashboardActivity.class);
        intent.putExtra(ApplicationConstants.BundleKeys.PATIENT_ID_BUNDLE, patient.getId());
        startActivity(intent);
    }

    @Override
    public void showUpgradeRegistrationModuleInfo() {
        ToastUtil.notifyLong(getResources().getString(R.string.registration_core_info));
    }

    public static AddEditPatientFragment newInstance() {
        return new AddEditPatientFragment();
    }

    private void resolveViews(View v) {
        relativeLayout = (RelativeLayout) v.findViewById(R.id.addEditRelativeLayout);
        edfname = (EditText) v.findViewById(R.id.firstname);
        edmname = (EditText) v.findViewById(R.id.middlename);
        edlname = (EditText) v.findViewById(R.id.surname);
        eddob = (EditText) v.findViewById(R.id.dob);
        edyr = (EditText) v.findViewById(R.id.estyr);
        edmonth = (EditText) v.findViewById(R.id.estmonth);
        edaddr1 = (EditText) v.findViewById(R.id.addr1);
        edaddr2 = (EditText) v.findViewById(R.id.addr2);
        edcity = (EditText) v.findViewById(R.id.city);
        edstate = (AutoCompleteTextView) v.findViewById(R.id.state);
        edcountry = (AutoCompleteTextView) v.findViewById(R.id.country);
        edpostal = (EditText) v.findViewById(R.id.postal);

        gen = (RadioGroup) v.findViewById(R.id.gender);
        progressBar = (ProgressBar) v.findViewById(R.id.progress_bar);

        fnameerror = (TextView) v.findViewById(R.id.fnameerror);
        lnameerror = (TextView) v.findViewById(R.id.lnameerror);
        doberror = (TextView) v.findViewById(R.id.doberror);
        gendererror = (TextView) v.findViewById(R.id.gendererror);
        addrerror = (TextView) v.findViewById(R.id.addrerror);
        countryerror = (TextView) v.findViewById(R.id.countryerror);

        submitConfirm = (Button) v.findViewById(R.id.submitConfirm);
        capturePhoto = (FloatingActionButton) v.findViewById(R.id.capture_photo);
        patientImageView = (ImageView) v.findViewById(R.id.patientPhoto);
    }

    private void fillFields(final Patient patient) {
        if (patient != null && patient.getPerson() != null) {
            //Change to Update Patient Form
            this.getActivity().setTitle("Update Patient");
            submitConfirm.setText("Update Patient");
            submitConfirm.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    mPresenter.confirmUpdate(updatePatient(patient));
                }
            });

            Person person = patient.getPerson();
            edfname.setText(person.getName().getGivenName());
            edmname.setText(person.getName().getMiddleName());
            edlname.setText(person.getName().getFamilyName());

            patientName = person.getName().getNameString();

            if (StringUtils.notNull(person.getBirthdate()) || StringUtils.notEmpty(person.getBirthdate())) {
                bdt = DateUtils.convertTimeString(person.getBirthdate());
                eddob.setText(DateUtils.convertTime(
                        DateUtils.convertTime(bdt.toString(), DateUtils.OPEN_MRS_REQUEST_FORMAT),
                        DateUtils.DEFAULT_DATE_FORMAT));
            }

            if (("M").equals(person.getGender())) {
                gen.check(R.id.male);
            } else if (("F").equals(person.getGender())) {
                gen.check(R.id.female);
            }

            edaddr1.setText(person.getAddress().getAddress1());
            edaddr2.setText(person.getAddress().getAddress2());
            edcity.setText(person.getAddress().getCityVillage());
            edstate.setText(person.getAddress().getStateProvince());
            edcountry.setText(person.getAddress().getCountry());
            edpostal.setText(person.getAddress().getPostalCode());

            if (patient.getPerson().getPhoto() != null) {
                patientPhoto = patient.getPerson().getPhoto();
                patientImageView.setImageBitmap(patient.getPerson().getPhoto());
            }
        }
    }

    private void addSuggestionsToAutoCompleTextView() {
        countries = getContext().getResources().getStringArray(R.array.countries_array);
        ArrayAdapter<String> adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_dropdown_item_1line,
                countries);
        edcountry.setAdapter(adapter);

    }

    private void addSuggestionsToCities() {
        String country_name = edcountry.getText().toString();
        country_name = country_name.replace("(", "");
        country_name = country_name.replace(")", "");
        country_name = country_name.replace(" ", "");
        country_name = country_name.replace("-", "_");
        country_name = country_name.replace(".", "");
        country_name = country_name.replace("'", "");
        int resourceId = this.getResources().getIdentifier(country_name.toLowerCase(), "array",
                getContext().getPackageName());
        if (resourceId != 0) {
            String[] states = getContext().getResources().getStringArray(resourceId);
            ArrayAdapter<String> state_adapter = new ArrayAdapter<>(getContext(),
                    android.R.layout.simple_dropdown_item_1line, states);
            edstate.setAdapter(state_adapter);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
            @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        AddEditPatientFragmentPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
    }

    private void addListeners() {
        gen.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            public void onCheckedChanged(RadioGroup rGroup, int checkedId) {
                gendererror.setVisibility(View.GONE);
            }
        });

        edcountry.setThreshold(2);
        edcountry.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (edcountry.getText().length() >= edcountry.getThreshold()) {
                    edcountry.showDropDown();
                }
                if (Arrays.asList(countries).contains(edcountry.getText().toString())) {
                    edcountry.dismissDropDown();
                }
            }
        });
        edstate.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                addSuggestionsToCities();
            }
        });
        if (eddob != null) {
            eddob.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int cYear;
                    int cMonth;
                    int cDay;

                    if (bdt == null) {
                        Calendar currentDate = Calendar.getInstance();
                        cYear = currentDate.get(Calendar.YEAR);
                        cMonth = currentDate.get(Calendar.MONTH);
                        cDay = currentDate.get(Calendar.DAY_OF_MONTH);
                    } else {
                        cYear = bdt.getYear();
                        cMonth = bdt.getMonthOfYear() - 1;
                        cDay = bdt.getDayOfMonth();
                    }

                    edmonth.getText().clear();
                    edyr.getText().clear();

                    DatePickerDialog mDatePicker = new DatePickerDialog(AddEditPatientFragment.this.getActivity(),
                            new DatePickerDialog.OnDateSetListener() {
                                public void onDateSet(DatePicker datepicker, int selectedyear, int selectedmonth,
                                        int selectedday) {
                                    int adjustedMonth = selectedmonth + 1;
                                    eddob.setText(selectedday + "/" + adjustedMonth + "/" + selectedyear);
                                    birthdate = new LocalDate(selectedyear, adjustedMonth, selectedday);
                                    bdt = birthdate.toDateTimeAtStartOfDay().toDateTime();
                                }
                            }, cYear, cMonth, cDay);
                    mDatePicker.getDatePicker().setMaxDate(System.currentTimeMillis());
                    mDatePicker.setTitle("Select Date");
                    mDatePicker.show();
                }
            });
        }

        capturePhoto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AddEditPatientFragmentPermissionsDispatcher.capturePhotoWithCheck(AddEditPatientFragment.this);
            }
        });

        submitConfirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mPresenter.confirmRegister(createPatient());
            }
        });

        patientImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (output != null) {
                    Intent i = new Intent(Intent.ACTION_VIEW);
                    i.setDataAndType(Uri.fromFile(output), "image/jpeg");
                    startActivity(i);
                } else if (patientPhoto != null) {
                    Intent intent = new Intent(getContext(), PatientPhotoActivity.class);
                    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                    patientPhoto.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
                    intent.putExtra("photo", byteArrayOutputStream.toByteArray());
                    intent.putExtra("name", patientName);
                    startActivity(intent);
                }
            }
        });

        TextWatcher textWatcher = new PatientBirthdateValidatorWatcher(eddob, edmonth, edyr);
        edmonth.addTextChangedListener(textWatcher);
        edyr.addTextChangedListener(textWatcher);
    }

    @NeedsPermission({ Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE })
    public void capturePhoto() {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (takePictureIntent.resolveActivity(getContext().getPackageManager()) != null) {
            File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
            output = new File(dir, getUniqueImageFileName());
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(output));
            startActivityForResult(takePictureIntent, IMAGE_REQUEST);
        }
    }

    @OnShowRationale({ Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE })
    public void showRationaleForCamera(final PermissionRequest request) {
        new AlertDialog.Builder(getActivity()).setMessage(R.string.permission_camera_rationale)
                .setPositiveButton(R.string.button_allow, (dialog, which) -> request.proceed())
                .setNegativeButton(R.string.button_deny, (dialog, button) -> request.cancel()).show();
    }

    @OnPermissionDenied({ Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE })
    public void showDeniedForCamera() {
        createSnackbarLong(R.string.permission_camera_denied).show();
    }

    @OnNeverAskAgain({ Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE })
    public void showNeverAskForCamera() {
        createSnackbarLong(R.string.permission_camera_neverask).show();
    }

    private Snackbar createSnackbarLong(int stringId) {
        Snackbar snackbar = Snackbar.make(relativeLayout, stringId, Snackbar.LENGTH_LONG);
        View sbView = snackbar.getView();
        TextView textView = (TextView) sbView.findViewById(android.support.design.R.id.snackbar_text);
        textView.setTextColor(Color.WHITE);
        return snackbar;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == IMAGE_REQUEST && resultCode == Activity.RESULT_OK) {
            patientPhoto = getPortraitImage(output.getPath());
            Bitmap bitmap = ThumbnailUtils.extractThumbnail(patientPhoto, patientImageView.getWidth(),
                    patientImageView.getHeight());
            patientImageView.setImageBitmap(bitmap);
            patientImageView.invalidate();
        }
    }

    private String getUniqueImageFileName() {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        return timeStamp + "_" + ".jpg";
    }

    private Bitmap getPortraitImage(String imagePath) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 4;
        Bitmap photo = BitmapFactory.decodeFile(output.getPath(), options);
        float rotateAngle;
        try {
            ExifInterface exifInterface = new ExifInterface(imagePath);
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_UNDEFINED);
            switch (orientation) {
            case ExifInterface.ORIENTATION_ROTATE_270:
                rotateAngle = 270;
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                rotateAngle = 180;
                break;
            case ExifInterface.ORIENTATION_ROTATE_90:
                rotateAngle = 90;
                break;
            default:
                rotateAngle = 0;
                break;
            }
            return rotateImage(photo, rotateAngle);
        } catch (IOException e) {
            logger.e(e.getMessage());
            return photo;
        }
    }

    public static Bitmap rotateImage(Bitmap source, float angle) {
        Matrix matrix = new Matrix();
        matrix.postRotate(angle);
        return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
    }
}