com.yattatech.dbtc.facade.SystemFacade.java Source code

Java tutorial

Introduction

Here is the source code for com.yattatech.dbtc.facade.SystemFacade.java

Source

/*
 * Copyright (c) 2014, Yatta Tech and/or its affiliates. All rights reserved.
 * YATTATECH PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.yattatech.dbtc.facade;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.zip.CRC32;
import java.util.zip.Checksum;

import org.apache.commons.io.IOUtils;

import twitter4j.Twitter;
import twitter4j.TwitterException;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcelable;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.yattatech.dbtc.Constants;
import com.yattatech.dbtc.activity.AsyncMessages;
import com.yattatech.dbtc.dao.SystemDao;
import com.yattatech.dbtc.dao.SystemPreferences;
import com.yattatech.dbtc.domain.Check;
import com.yattatech.dbtc.domain.Task;
import com.yattatech.dbtc.domain.TaskList;
import com.yattatech.dbtc.domain.TwitterLoginStatus;
import com.yattatech.dbtc.io.BackupInputStream;
import com.yattatech.dbtc.log.Debug;
import com.yattatech.dbtc.receiver.Broadcaster;
import com.yattatech.dbtc.util.TwitterUtil;

/**
 * Facade as entry point to all application 
 * logic.
 * 
 * @author Adriano Braga Alencar (adrianobragaalencar@gmail.com) 
 * 
 */
public final class SystemFacade {

    public static final String TAG = "SystemFacade";
    public static final SystemFacade UNIQUE = new SystemFacade();
    private final SystemDao mDao = new SystemDao();
    private final SystemPreferences mPrefs = new SystemPreferences();
    private final ExecutorService mExecutor;

    private SystemFacade() {
        mExecutor = Executors.newFixedThreadPool(Constants.DEFAULT_THREADS_NUM);
        // To guarantee that executor will be killed as soon as 
        // vm halt
        Runtime.getRuntime().addShutdownHook(new Thread() {

            /*
             * (non-Javadoc)
             * @see java.lang.Thread#run()
             */
            @Override
            public void run() {
                mExecutor.shutdown();
            }
        });
    }

    public void editTask(final Task task) {
        if (task == null) {
            throw new IllegalArgumentException("Task cannot be null");
        }
        Debug.d(TAG, "editTask");
        mExecutor.execute(new Runnable() {

            /*
             * (non-Javadoc)
             * @see java.lang.Runnable#run()
             */
            @Override
            public void run() {
                final Task returned = mDao.editTask(task);
                final Intent intent = new Intent(AsyncMessages.EDIT_TASK_ACTION);
                // To avoid messing around with Serializable overload
                // method
                intent.putExtra(Constants.TASK_KEY, (Parcelable) returned);
                Broadcaster.sendLocalMessage(intent);
            }
        });
    }

    public void restoreTasks(final List<Task> tasks) {
        if (Debug.isDebugable()) {
            Debug.d(TAG, "restoreTasks tasks=" + tasks);
        }
        mExecutor.execute(new Runnable() {

            /*
             * (non-Javadoc)
             * @see java.lang.Runnable#run()
             */
            @Override
            public void run() {
                final boolean result = mDao.restoreTasks(tasks);
                final Intent intent = new Intent(AsyncMessages.BACKUP_RESTORE_ACTION);
                intent.putExtra(Constants.RESTORE_KEY, result);
                Broadcaster.sendLocalMessage(intent);
            }
        });
    }

    public void addNewTask(final String name, final boolean defined, final int maxDays) {
        if (name == null) {
            throw new IllegalArgumentException("Taskname cannot be null");
        }
        Debug.d(TAG, "addNewTask");
        mExecutor.execute(new Runnable() {

            /*
             * (non-Javadoc)
             * @see java.lang.Runnable#run()
             */
            @Override
            public void run() {
                final Task task = mDao.addNewTask(name, defined, maxDays);
                final Intent intent = new Intent(AsyncMessages.ADD_NEW_TASK_ACTION);
                // To avoid messing around with Serializable overload
                // method
                intent.putExtra(Constants.TASK_KEY, (Parcelable) task);
                Broadcaster.sendLocalMessage(intent);
            }
        });
    }

    public void removeTask(final Task task) {
        if (task == null) {
            throw new IllegalArgumentException("Task cannot be null");
        }
        Debug.d(TAG, "removeTask");
        mExecutor.execute(new Runnable() {

            /*
             * (non-Javadoc)
             * @see java.lang.Runnable#run()
             */
            @Override
            public void run() {
                final Task returned = mDao.removeTask(task);
                final Intent intent = new Intent(AsyncMessages.REMOVE_TASK_ACTION);
                intent.putExtra(Constants.TASK_KEY, (Parcelable) returned);
                Broadcaster.sendLocalMessage(intent);
            }
        });
    }

    public List<Task> getTasks() {
        Debug.d(TAG, "getTasks");
        return mDao.getTasks();
    }

    private List<Task> getTasksWithChecks() {
        Debug.d(TAG, "getTasksWithChecks");
        return mDao.getTasksWithChecks();
    }

    public boolean isTwitterLogged() {
        Debug.d(TAG, "isTwitterLogged");
        return mPrefs.isTwitterLogged();
    }

    public void setTwitterData(final Bundle bundle) {
        Debug.d(TAG, "setTwitterData");
        mExecutor.execute(new Runnable() {

            /*
             * (non-Javadoc)
             * @see java.lang.Runnable#run()
             */
            @Override
            public void run() {
                final TwitterLoginStatus status = mPrefs.setTwitterData(bundle);
                if (Debug.isDebugable()) {
                    Debug.d(TAG, "setTwitterData=" + status.name());
                }
                final Intent intent = new Intent(AsyncMessages.TWITTER_LOGIN_ACTION);
                // To avoid messing around with Serializable overload
                // method
                intent.putExtra(Constants.TWITTER_LOGIN_KEY, (Parcelable) status);
                Broadcaster.sendLocalMessage(intent);

            }
        });
    }

    public void sendTwitterMsg(final String msg) {
        if (Debug.isDebugable()) {
            Debug.d(TAG, "sendTwitterMsg " + msg);
        }
        mExecutor.execute(new Runnable() {

            /*
             * (non-Javadoc)
             * @see java.lang.Runnable#run()
             */
            @Override
            public void run() {
                final Twitter twitter = TwitterUtil.getTwitter();
                try {
                    twitter.setOAuthAccessToken(mPrefs.getTwitterAccessToken());
                    twitter.updateStatus(msg);
                } catch (TwitterException te) {
                    Debug.d(TAG, "Failed: ", te);
                }
            }
        });
    }

    public void twitterLogout() {
        Debug.d(TAG, "twitterLogout");
        mExecutor.execute(new Runnable() {

            /*
             * (non-Javadoc)
             * @see java.lang.Runnable#run()
             */
            @Override
            public void run() {
                mPrefs.twitterLogout();
            }
        });
    }

    public void dropboxLogout() {
        Debug.d(TAG, "dropboxLogout");
        mExecutor.execute(new Runnable() {

            /*
             * (non-Javadoc)
             * @see java.lang.Runnable#run()
             */
            @Override
            public void run() {
                mPrefs.dropboxLogout();
            }
        });
    }

    public void setDropBoxToken(final String token) {
        Debug.d(TAG, "setDropBoxToken");
        mExecutor.execute(new Runnable() {

            /*
             * (non-Javadoc)
             * @see java.lang.Runnable#run()
             */
            @Override
            public void run() {
                mPrefs.setDropBoxToken(token);
            }
        });
    }

    public boolean hasTasks() {
        Debug.d(TAG, "getDropBoxToken");
        return mDao.hasTasks();
    }

    public String getDropBoxToken() {
        Debug.d(TAG, "getDropBoxToken");
        return mPrefs.getDropBoxToken();
    }

    public void saveCheck(final int year, final int month, final int day, final int taskId) {
        if (Debug.isDebugable()) {
            Debug.d(TAG, "check year=" + year + " month=" + month + " day=" + day + " taskId=" + taskId);
        }
        mExecutor.execute(new Runnable() {

            /*
             * (non-Javadoc)
             * @see java.lang.Runnable#run()
             */
            @Override
            public void run() {
                mDao.saveCheck(year, month, day, taskId);
            }
        });
    }

    public void removeCheck(final int year, final int month, final int day, final int taskId) {
        if (Debug.isDebugable()) {
            Debug.d(TAG, "check year=" + year + " month=" + month + " day=" + day + " taskId=" + taskId);
        }
        mExecutor.execute(new Runnable() {

            /*
             * (non-Javadoc)
             * @see java.lang.Runnable#run()
             */
            @Override
            public void run() {
                mDao.removeCheck(year, month, day, taskId);
            }
        });
    }

    public BackupInputStream getBackupInputStream() throws IOException {
        Debug.d(TAG, "getBackupInputStream");
        final List<Task> tasks = getTasksWithChecks();
        final TaskList taskList = new TaskList();
        final GsonBuilder builder = new GsonBuilder();
        builder.excludeFieldsWithoutExposeAnnotation();
        final Gson gson = builder.create();
        final Type type = new TypeToken<List<Task>>() {
        }.getType();
        final String json = gson.toJson(tasks, type);
        taskList.mChecksum = calculateChecksum(json);
        taskList.mTasks = tasks;
        final String json2 = gson.toJson(taskList);
        final BackupInputStream in = new BackupInputStream(IOUtils.toInputStream(json2, "UTF-8"));
        in.mLength = json2.length();
        if (Debug.isDebugable()) {
            Debug.d(TAG, "tasks=" + tasks.size() + " json=" + json + " length=" + in.mLength);
        }
        return in;
    }

    public List<Task> getTasksFromJson(final String json) {
        if (Debug.isDebugable()) {
            Debug.d(TAG, "getTasksFromJson json=" + json);
        }
        final Type type = new TypeToken<List<Task>>() {
        }.getType();
        final GsonBuilder builder = new GsonBuilder();
        builder.excludeFieldsWithoutExposeAnnotation();
        final Gson gson = builder.create();

        final TaskList taskList = gson.fromJson(json, TaskList.class);
        if (taskList != null) {
            final long checksum = taskList.mChecksum;
            final String json2 = gson.toJson(taskList.mTasks, type);
            if (isChecksumValid(checksum, json2)) {
                return taskList.mTasks;
            }
        }
        return null;
    }

    public List<Check> getChecksByTaskAndDate(final Task task, final Calendar date) {
        if (Debug.isDebugable()) {
            Debug.d(TAG, "getChecksByTaskAndDate task=" + task + "date=" + date);
        }
        return mDao.getChecksByTaskAndDate(task, date);
    }

    public int getChecksCountByTask(final Task task) {
        if (Debug.isDebugable()) {
            Debug.d(TAG, "getChecksCountByTask task=" + task);
        }
        return mDao.getChecksCountByTask(task);
    }

    /**
     * Actually that only checks if current year is less than
     * Minimum one supported by application. That values is 
     * the 2nd position in {@link Constants#MIN_CALENDAR_DATE}
     * 
     * @return boolean 
     */
    public boolean isDeviceClockOutOfSync() {
        final Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        final int year = calendar.get(Calendar.YEAR);
        final int minYear = Constants.MIN_CALENDAR_DATE[1];
        if (Debug.isDebugable()) {
            Debug.d(TAG, "isDeviceClockOutOfSync currentYear=" + year + "minimulSupportedYear=" + minYear);
        }
        return year < minYear;
    }

    public boolean isTaskChecked(Task task) {
        return mDao.isTaskChecked(task);
    }

    public void saveDataOrder(List<Task> tasks) {
        if (Debug.isDebugable()) {
            Debug.d(TAG, "saveDataOrder tasks=" + tasks);
        }
        mPrefs.saveDataOrder(tasks);
    }

    public List<Task> restoreDataOrder(List<Task> tasks) {
        if (Debug.isDebugable()) {
            Debug.d(TAG, "restoreDataOrder tasks=" + tasks);
        }
        return mPrefs.restoreDataOrder(tasks);
    }

    private long calculateChecksum(String json) {
        final byte[] input = json.getBytes();
        final Checksum checksum = new CRC32();
        checksum.update(input, 0, input.length);
        final long checksumValue = checksum.getValue();
        if (Debug.isDebugable()) {
            Debug.d(TAG, "calculate checksum for json=" + json + "\nvalue=" + checksumValue);
        }
        return checksumValue;
    }

    private boolean isChecksumValid(long checksumValue, String json) {
        final byte[] input = json.getBytes();
        final Checksum checksum = new CRC32();
        checksum.update(input, 0, input.length);
        final long returned = checksum.getValue();
        if (Debug.isDebugable()) {
            Debug.d(TAG, "validate checksum for json=" + json + "\nexpected=" + checksumValue + "\nretrieve="
                    + returned);
        }
        return checksumValue == returned;
    }
}