org.mifos.androidclient.templates.OperationFormActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.mifos.androidclient.templates.OperationFormActivity.java

Source

/*
 * Copyright (c) 2005-2011 Grameen Foundation USA
 * All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *
 * See also http://www.apache.org/licenses/LICENSE-2.0.html for an
 * explanation of the license and how it is applied.
 */

package org.mifos.androidclient.templates;

import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.InputType;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
import org.codehaus.jackson.JsonGenerationException;
import org.mifos.androidclient.R;
import org.mifos.androidclient.entities.SessionStatus;
import org.mifos.androidclient.main.LoginActivity;
import org.mifos.androidclient.net.services.LoginService;
import org.mifos.androidclient.net.services.SessionStatusService;
import org.mifos.androidclient.util.ServerMessageTranslator;
import org.mifos.androidclient.util.ui.TableLayoutHelper;
import org.springframework.web.client.RestClientException;

import java.io.IOException;
import java.io.Serializable;
import java.util.*;

/**
 * A base class for forms used to perform operations on Mifos customers
 * and accounts.
 */
public abstract class OperationFormActivity extends MifosActivity
        implements DatePickerDialog.OnDateSetListener, View.OnFocusChangeListener {

    private static final String PREVIOUS_STATE_BUNDLE_KEY = OperationFormActivity.class.getSimpleName()
            + "-previousState";
    private static final int DATE_DIALOG_ID = 0;

    public final static String STATUS_KEY = "status";
    public final static String STATUS_SUCCESS = "success";
    public final static String STATUS_ERROR = "error";
    public final static String STATUS_INTERRUPT = "interrupt";
    public final static String CAUSE_KEY = "cause";

    private LinearLayout mFormFields;
    private TextView mCurrentlySetTextView;

    private LoginService mLoginService;
    private SessionStatusService mSessionStatusService;

    private FormSubmissionTask mFormSubmissionTask;

    private ServerMessageTranslator mTranslator;

    private Map<String, String> mPreviousResult;
    private boolean mLoginRequired;

    @Override
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.operation_form);

        mFormFields = (LinearLayout) findViewById(R.id.operationForm_formFields);
        mLoginService = new LoginService(this);
        mSessionStatusService = new SessionStatusService(this);
    }

    @Override
    protected void onRestoreInstanceState(Bundle bundle) {
        super.onRestoreInstanceState(bundle);
        if (bundle != null && bundle.containsKey(PREVIOUS_STATE_BUNDLE_KEY)) {
            mPreviousResult = (Map<String, String>) bundle.get(PREVIOUS_STATE_BUNDLE_KEY);
            updateViewForResponse(mPreviousResult);
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putSerializable(PREVIOUS_STATE_BUNDLE_KEY, (Serializable) mPreviousResult);
    }

    public void setFormHeader(String value) {
        TextView header = (TextView) findViewById(R.id.operationForm_header);
        header.setText(value);
    }

    public void setFormAdditionalInformation(String value) {
        TextView additionalInformation = (TextView) findViewById(R.id.operationForm_additionalInformation);
        additionalInformation.setText(value);
    }

    public void setStatus(boolean success) {
        TextView status = (TextView) findViewById(R.id.operationForm_status);
        if (success) {
            status.setText(getString(R.string.operationForm_status_success));
            status.setTextColor(getResources().getColor(R.color.successGreen));
        } else {
            status.setText(getString(R.string.operationForm_status_error));
            status.setTextColor(getResources().getColor(R.color.errorRed));
        }
    }

    public void setOperationSummaryContent(Map<String, String> operationResults) {
        TableLayout operationSummary = (TableLayout) findViewById(R.id.operationForm_operationSummary);
        TableLayoutHelper helper = new TableLayoutHelper(this);
        operationSummary.removeAllViews();
        for (Map.Entry<String, String> entry : operationResults.entrySet()) {
            if (!entry.getKey().equals(STATUS_KEY)) {
                TableRow row = helper.createTableRow();
                TextView cell = helper.createTableCell(
                        ServerMessageTranslator.translate(this, entry.getKey(), entry.getKey()), 1);
                row.addView(cell);
                cell = helper.createTableCell(
                        ServerMessageTranslator.translate(this, entry.getValue(), entry.getValue()), 2);
                row.addView(cell);
                operationSummary.addView(row);
            }
        }
    }

    public CheckBox addCheckBoxFormField(String fieldLabel) {
        LinearLayout field = (LinearLayout) getLayoutInflater().inflate(R.layout.check_box_form_field, null);
        CheckBox input = (CheckBox) field.findViewById(R.id.checkBox_label);
        input.setText(fieldLabel);
        input.setInputType(InputType.TYPE_NULL);
        mFormFields.addView(field, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT));
        return input;
    }

    public EditText addDateFormField(String fieldLabel) {
        LinearLayout field = (LinearLayout) getLayoutInflater().inflate(R.layout.date_form_field, null);
        TextView label = (TextView) field.findViewById(R.id.dateFormField_label);
        label.setText(fieldLabel);
        EditText input = (EditText) field.findViewById(R.id.dateFormField_input);
        input.setInputType(InputType.TYPE_NULL);
        input.setOnFocusChangeListener(this);
        mFormFields.addView(field, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT));
        return input;
    }

    public Spinner addComboBoxFormField(String fieldLabel, List<String> elements) {
        LinearLayout field = (LinearLayout) getLayoutInflater().inflate(R.layout.combo_box_form_field, null);
        TextView label = (TextView) field.findViewById(R.id.comboBoxFormField_label);
        label.setText(fieldLabel);
        Spinner input = (Spinner) field.findViewById(R.id.comboBoxFormField_input);
        input.setPrompt(fieldLabel);
        input.setAdapter(new ArrayAdapter(this, R.layout.combo_box_item, elements));
        mFormFields.addView(field, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT));
        return input;
    }

    public void replaceComboBoxItems(Spinner comboBox, List<String> items) {
        comboBox.setAdapter(new ArrayAdapter(this, R.layout.combo_box_item, items));
    }

    public void setInputEnabled(EditText input, boolean editable) {
        input.setEnabled(editable);
    }

    public EditText addTextFormField(String fieldLabel) {
        return addFormField(fieldLabel, InputType.TYPE_CLASS_TEXT);
    }

    public EditText addDecimalNumberFormField(String fieldLabel) {
        return addFormField(fieldLabel, InputType.TYPE_NUMBER_FLAG_DECIMAL);
    }

    private EditText addFormField(String fieldLabel, int inputType) {
        LinearLayout field = (LinearLayout) getLayoutInflater().inflate(R.layout.edit_text_form_field, null);
        TextView label = (TextView) field.findViewById(R.id.editTextFormField_label);
        label.setText(fieldLabel);
        EditText input = (EditText) field.findViewById(R.id.editTextFormField_input);
        input.setInputType(inputType);
        mFormFields.addView(field, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT));
        return input;
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        Dialog dialog;
        switch (id) {
        case DATE_DIALOG_ID:
            Calendar today = Calendar.getInstance();
            return new DatePickerDialog(this, this, today.get(Calendar.YEAR), today.get(Calendar.MONTH),
                    today.get(Calendar.DAY_OF_MONTH));
        default:
            dialog = null;
        }
        return dialog;
    }

    @Override
    public void onDateSet(DatePicker datePicker, int year, int monthOfYear, int dayOfMonth) {
        StringBuilder builder = new StringBuilder().append(String.format("%02d", dayOfMonth)).append("-")
                .append(String.format("%02d", monthOfYear + 1)).append("-").append(year);
        mCurrentlySetTextView.setText(builder.toString());
    }

    public void setSubmissionButtonSet() {
        Button button;
        button = (Button) findViewById(R.id.operationForm_submitButton);
        setViewVisible(button, true);
        button = (Button) findViewById(R.id.operationForm_goBackButton);
        setViewVisible(button, true);
        button = (Button) findViewById(R.id.operationForm_okButton);
        setViewVisible(button, false);
    }

    public void setSuccessButtonSet() {
        Button button;
        button = (Button) findViewById(R.id.operationForm_submitButton);
        setViewVisible(button, false);
        button = (Button) findViewById(R.id.operationForm_goBackButton);
        setViewVisible(button, false);
        button = (Button) findViewById(R.id.operationForm_okButton);
        setViewVisible(button, true);
    }

    public void setStatusVisible(boolean visible) {
        TextView view = (TextView) findViewById(R.id.operationForm_status_label);
        setViewVisible(view, visible);
        view = (TextView) findViewById(R.id.operationForm_status);
        setViewVisible(view, visible);
    }

    public void setAdditionalInformationVisible(boolean visible) {
        TextView additionalInformation = (TextView) findViewById(R.id.operationForm_additionalInformation);
        setViewVisible(additionalInformation, visible);
    }

    public void setOperationSummaryVisible(boolean visible) {
        TableLayout operationSummary = (TableLayout) findViewById(R.id.operationForm_operationSummary);
        setViewVisible(operationSummary, visible);
    }

    public void setFormFieldsVisible(boolean visible) {
        LinearLayout formFields = (LinearLayout) findViewById(R.id.operationForm_formFields);
        setViewVisible(formFields, visible);
    }

    /**
     * Called when a date form field is clicked.
     *
     * @param view the form input which has been clicked
     */
    public void onDateFieldClicked(View view) {
        dateFieldEdit(view);
    }

    @Override
    public void onFocusChange(View view, boolean hasFocus) {
        if (hasFocus) {
            dateFieldEdit(view);
        }
    }

    public void dateFieldEdit(View view) {
        mCurrentlySetTextView = (TextView) view;
        showDialog(DATE_DIALOG_ID);
    }

    public void onOkPressed(View view) {
        setResult(Activity.RESULT_OK);
        finish();
    }

    public void onSubmitPressed(View view) throws IOException {
        runFormSubmissionTask(onPrepareParameters());
    }

    public void onGoBackPressed(View view) {
        setResult(Activity.RESULT_CANCELED);
        finish();
    }

    private void setViewVisible(View view, boolean visible) {
        if (visible) {
            view.setVisibility(View.VISIBLE);
        } else {
            view.setVisibility(View.GONE);
        }
    }

    public boolean isLoginRequired() {
        synchronized (this) {
            return mLoginRequired;
        }
    }

    public void setLoginRequired(boolean loginRequired) {
        synchronized (this) {
            this.mLoginRequired = loginRequired;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
        case LoginActivity.REQUEST_CODE:
            switch (resultCode) {
            case Activity.RESULT_OK:
                break;
            case Activity.RESULT_CANCELED:
                finish();
                break;
            default:
                break;
            }
            break;
        default:
            break;
        }
    }

    protected abstract Map<String, String> onPrepareParameters() throws IOException;

    protected abstract Map<String, String> onFormSubmission(Map<String, String> parameters);

    protected void onSubmissionResult(Map<String, String> result) {
        mPreviousResult = result;
        updateViewForResponse(result);
    }

    protected void updateViewForResponse(Map<String, String> result) {
        if (result != null && result.containsKey(STATUS_KEY)) {
            if (result.get(STATUS_KEY).equals(STATUS_SUCCESS)) {
                setSuccessView(result);
            } else if (result.get(STATUS_KEY).equals(STATUS_ERROR)) {
                setErrorView(result);
            } else if (result.get(STATUS_KEY).equals(STATUS_INTERRUPT)) {
                setInterruptView(result);
            } else {
                setUnknownProblemView();
            }
        }
    }

    protected void setSuccessView(Map<String, String> summary) {
        setStatus(true);
        setStatusVisible(true);
        setSuccessButtonSet();
        setFormFieldsVisible(false);
        setOperationSummaryContent(summary);
        setOperationSummaryVisible(true);
    }

    protected void setInterruptView(Map<String, String> summary) {
        setStatus(true);
        setStatusVisible(true);
        setSuccessButtonSet();
        setFormFieldsVisible(false);
        Map<String, String> interruptSummary = new HashMap<String, String>();
        interruptSummary.put(getString(R.string.operationForm_interruptCause_label), summary.get(CAUSE_KEY));
        setOperationSummaryContent(interruptSummary);
        setOperationSummaryVisible(true);
    }

    protected void setErrorView(Map<String, String> summary) {
        setStatus(false);
        setStatusVisible(true);
        setSuccessButtonSet();
        setFormFieldsVisible(true);
        Map<String, String> errorCause = new HashMap<String, String>();
        errorCause.put(CAUSE_KEY, summary.get(CAUSE_KEY));
        setOperationSummaryContent(errorCause);
        setOperationSummaryVisible(true);
    }

    protected void setUnknownProblemView() {
        setStatus(false);
        setStatusVisible(true);
        setSubmissionButtonSet();
        setFormFieldsVisible(true);
        Map<String, String> unknownProblemSummary = new HashMap<String, String>();
        unknownProblemSummary.put(getString(R.string.operationForm_unknownProblem_label),
                getString(R.string.operationForm_unknownProblem_desc));
        setOperationSummaryVisible(true);
        setOperationSummaryContent(unknownProblemSummary);
    }

    protected void runFormSubmissionTask(Map<String, String> parameters) {
        if (mFormSubmissionTask == null || mFormSubmissionTask.getStatus() != AsyncTask.Status.RUNNING) {
            setLoginRequired(false);
            mFormSubmissionTask = new FormSubmissionTask(this, getString(R.string.dialog_loading_message),
                    getString(R.string.dialog_submitting_data));
            mFormSubmissionTask.execute(parameters);
        }
    }

    private class FormSubmissionTask
            extends ServiceConnectivityTask<Map<String, String>, Void, Map<String, String>> {

        public FormSubmissionTask(Context context, String progressTitle, String progressMessage) {
            super(context, progressTitle, progressMessage);
        }

        @Override
        protected Map<String, String> doInBackgroundBody(Map<String, String>... params)
                throws RestClientException, IllegalArgumentException {
            Map<String, String> result = null;
            SessionStatus status = mSessionStatusService.getSessionStatus();
            if (status.isSuccessful()) {
                result = onFormSubmission(params[0]);
            } else {
                if (hasUserCredentials()) {
                    status = mLoginService.logIn(getUserLogin(), getUserPassword());
                    if (status.isSuccessful()) {
                        result = onFormSubmission(params[0]);
                    } else {
                        setTerminated(true);
                        setLoginRequired(true);
                    }
                }
            }
            return result;
        }

        @Override
        protected void onPostExecuteBody(Map<String, String> result) {
            if (isLoginRequired()) {
                Intent intent = new Intent().setClass(mContext, LoginActivity.class);
                startActivityForResult(intent, LoginActivity.REQUEST_CODE);
            } else {
                onSubmissionResult(result);
            }
        }

    }

}