net.ausgstecktis.DAL.MigrationProxy.java Source code

Java tutorial

Introduction

Here is the source code for net.ausgstecktis.DAL.MigrationProxy.java

Source

/***
 * Copyright (C) 2011  naikon, wexoo
 * android@geekosphere.org
 *
 * 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 net.ausgstecktis.DAL;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import net.ausgstecktis.R;
import net.ausgstecktis.entities.City;
import net.ausgstecktis.entities.District;
import net.ausgstecktis.entities.Heuriger;
import net.ausgstecktis.entities.OpenDay;
import net.ausgstecktis.entities.OpenTime;
import net.ausgstecktis.entities.OpeningCalendar;
import net.ausgstecktis.entities.Region;
import net.ausgstecktis.ui.HeurigenApp;
import net.ausgstecktis.ui.PreferencesActivity;
import net.wexoo.organicdroid.Log;
import net.wexoo.organicdroid.convert.DateAndTimeConverter;
import net.wexoo.organicdroid.convert.NumberConverter;

import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.os.Environment;

import com.j256.ormlite.android.apptools.OpenHelperManager;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.stmt.UpdateBuilder;

/**
 * MigrationProxy.java
 * 
 * @author wexoo
 */
public class MigrationProxy {

    private static final String TAG = MigrationProxy.class.getSimpleName();
    public static final String DB_PATH = Environment.getDataDirectory() + "/data/net.ausgstecktis/databases/";
    public static final String CREATED_HEURIGE_KEY = "c_heurige";
    public static final String UPDATE_HEURIGE_KEY = "u_heurige";
    public static final String CREATED_CALENDAR_KEY = "c_calendar";
    public static final String UPDATED_CALENDAR_KEY = "u_calendar";

    private static MigrationProxy instance;

    private static OrmLiteSqliteOpenHelper helper;
    private static OfflineProxy offlineProxy;
    private RestClient currentRestClient;

    private static ArrayList<Heuriger> favoriteHeurigeList;

    public static MigrationProxy getInstance() {
        return getInstance(HeurigenApp.mainContext);
    }

    /**
     * Gets the single instance of MigrationProxy.
     */
    public static MigrationProxy getInstance(Context context) {
        if (MigrationProxy.instance == null)
            MigrationProxy.instance = new MigrationProxy();

        if (helper == null)
            helper = OpenHelperManager.getHelper(HeurigenApp.mainContext);

        Log.d(TAG, "Helper fetched using current context!");
        return instance;
    }

    /**
     * @author wexoo
     */
    public boolean isLocalDatabasePresent() {
        try {
            final Dao<Heuriger, Integer> objectDao = helper.getDao(Heuriger.class);

            return objectDao.isTableExists()
                    && !objectDao.queryRaw("select count(*) from " + Heuriger.TABLE_NAME).getResults().get(0)[0]
                            .equals("0");
        } catch (final SQLException e) {
            Log.e(TAG, e.getMessage());
            e.printStackTrace();
        }
        return false;
    }

    /**
     * Store old favorite heurige.
     */
    public void storeOldFavoriteHeurige() {
        favoriteHeurigeList = getOfflineProxy().getFavoriteHeurige();
    }

    /**
     * Creates an empty database on the system and rewrites it with your own database.
     * 
     * @author wexoo
     */
    public void createDataBase(final boolean migrateLocalDatabase) {

        /*
         * By calling this method an empty database will be created into the default
         * system path of your application so we will be able to overwrite that
         * database with our database.
         */
        helper.getReadableDatabase();

        try {
            boolean migrateFavorites = isLocalDatabasePresent();

            if (migrateFavorites)
                instance.storeOldFavoriteHeurige();

            if (migrateLocalDatabase)
                copyDataBase();
            else
                copyOnlineDataBase();

            if (migrateFavorites)
                instance.markFavoriteHeurigeInNewDatabase();
            //         helper.close();
        } catch (final IOException e) {
            throw new Error("Error copying database");
        }
    }

    /**
     * Copies your database from your local assets-folder to the just created
     * empty database in the system folder, from where it can be accessed and
     * handled. This is done by transfering bytestream.
     * 
     * @throws IOException if an input or output exception occurred
     * @author wexoo
     */
    private void copyDataBase() throws IOException {

        Log.d(TAG, "starting to copy database");

        // Open your local db as the input stream
        final InputStream myInput = HeurigenApp.mainContext.getAssets()
                .open(HeurigenApp.getSettings().databaseName());

        // Path to the just created empty db
        final String outFileName = DB_PATH + HeurigenApp.getSettings().databaseName();

        // Open the empty db as the output stream
        final OutputStream myOutput = new FileOutputStream(outFileName);

        // transfer bytes from the inputfile to the outputfile
        final byte[] buffer = new byte[1024];
        int length;
        while ((length = myInput.read(buffer)) > 0)
            myOutput.write(buffer, 0, length);

        // Close the streams
        myOutput.flush();
        myOutput.close();
        myInput.close();
    }

    /**
     * Copies the online database version in the system folder
     * from where it can be accessed and handled.
     * This is done by transfering bytestream.
     * 
     * @throws IOException if the file/path is not read or writeable
     * @author naikon
     */
    private void copyOnlineDataBase() throws IOException {

        prepareRestClientAndCallWebService(RestClient.GET_DOWNLOAD_DB, RestClient.DB);

        //get http enity
        final HttpEntity entity = currentRestClient.getHttpEntity();

        // Path to the just created empty db
        final String outFileName = DB_PATH + HeurigenApp.getSettings().databaseName();

        // Open the empty db as the output stream
        final OutputStream output = new FileOutputStream(outFileName);

        final InputStream in = entity.getContent();

        final byte[] buffer = new byte[1024];
        int len1 = 0;
        while ((len1 = in.read(buffer)) > 0)
            output.write(buffer, 0, len1);
        output.close();
        in.close();
    }

    /**
     * Import favorite heurige to new database.
     */
    private void markFavoriteHeurigeInNewDatabase() {

        try {
            final Dao<Heuriger, Integer> objectDao = helper.getDao(Heuriger.class);

            for (final Heuriger heuriger : favoriteHeurigeList) {

                final UpdateBuilder<Heuriger, Integer> update = objectDao.updateBuilder();

                update.updateColumnValue(Heuriger.FAVORITE_COLUMN, heuriger.getFavorite());
                update.where().eq(Heuriger.ID_COLUMN, heuriger.getId());
                objectDao.update(update.prepare());
            }
            favoriteHeurigeList = null;

        } catch (final SQLException e) {
            Log.e(TAG, e.getMessage());
        }
    }

    public Map<String, Integer> getUpdateInfo() {

        prepareRestClientAndCallWebServiceWithLastUpdateDateAttached(RestClient.GET_UPDATE_INFO, RestClient.GET);

        try {
            if (currentRestClient.getObjectJson() != null) {
                final JSONArray jArray = currentRestClient.getObjectJson();
                Map<String, Integer> updateQuantities = new HashMap<String, Integer>(4);

                for (int i = 0; i < jArray.length(); i++) {
                    final JSONObject jsonData = jArray.getJSONObject(i);

                    updateQuantities.put(CREATED_HEURIGE_KEY,
                            NumberConverter.getIntegerValueOfString(jsonData.getString(CREATED_HEURIGE_KEY)));
                    updateQuantities.put(UPDATE_HEURIGE_KEY,
                            NumberConverter.getIntegerValueOfString(jsonData.getString(UPDATE_HEURIGE_KEY)));
                    updateQuantities.put(CREATED_CALENDAR_KEY,
                            NumberConverter.getIntegerValueOfString(jsonData.getString(CREATED_CALENDAR_KEY)));
                    updateQuantities.put(UPDATED_CALENDAR_KEY,
                            NumberConverter.getIntegerValueOfString(jsonData.getString(UPDATED_CALENDAR_KEY)));

                }
                Log.d(TAG, CREATED_HEURIGE_KEY + ": " + updateQuantities.get(CREATED_HEURIGE_KEY));
                Log.d(TAG, UPDATE_HEURIGE_KEY + ": " + updateQuantities.get(UPDATE_HEURIGE_KEY));
                Log.d(TAG, CREATED_CALENDAR_KEY + ": " + updateQuantities.get(CREATED_CALENDAR_KEY));
                Log.d(TAG, UPDATED_CALENDAR_KEY + ": " + updateQuantities.get(UPDATED_CALENDAR_KEY));

                return updateQuantities;
            } else
                Log.e(TAG, "Returned objectJSON is null!");
        } catch (final JSONException e) {
            Log.e(TAG, "Error parsing data " + e.toString());
        }
        return null;
    }

    public void getNewAndUpdatedCities() {

        Log.d(TAG, "vor getHeurige offlineproxy zugriff");

        getOfflineProxy();

        Log.d(TAG, "nach getHeurige offlineproxy zugriff");

        prepareRestClientAndCallWebServiceWithLastUpdateDateAttached(RestClient.GET_NEW_AND_UPDATED_CITIES,
                RestClient.GET);

        try {
            if (currentRestClient.getObjectJson() != null) {
                final JSONArray jArray = currentRestClient.getObjectJson();

                for (int i = 0; i < jArray.length(); i++) {
                    final JSONObject jsonData = jArray.getJSONObject(i);

                    Region region = new Region(NumberConverter.getIntegerValueOfString(jsonData.getString("r_id")),
                            jsonData.getString("r_name"));

                    final Dao<Region, Integer> regionDao = helper.getDao(Region.class);
                    regionDao.createOrUpdate(region);

                    District district = new District(
                            NumberConverter.getIntegerValueOfString(jsonData.getString("d_id")),
                            jsonData.getString("d_kbz"), jsonData.getString("d_name"));

                    final Dao<District, Integer> districtDao = helper.getDao(District.class);
                    districtDao.createOrUpdate(district);

                    City city = new City(NumberConverter.getIntegerValueOfString(jsonData.getString("c_id")),
                            jsonData.getString("c_name"),
                            NumberConverter.getIntegerValueOfString(jsonData.getString("c_zipcode")), district,
                            region);

                    final Dao<City, Integer> cityDao = helper.getDao(City.class);
                    cityDao.createOrUpdate(city);
                }
            } else
                Log.e(TAG, "Returned objectJSON is null!");
        } catch (final JSONException e) {
            Log.e(TAG, "Error parsing data " + e.toString());
        } catch (final SQLException e) {
            Log.e(TAG, e.getMessage());
        }
    }

    public void getNewAndUpdatedHeurige() {

        prepareRestClientAndCallWebServiceWithLastUpdateDateAttached(RestClient.GET_NEW_AND_UPDATED_HEURIGE,
                RestClient.GET);

        try {
            if (currentRestClient.getObjectJson() != null) {
                final JSONArray jArray = currentRestClient.getObjectJson();

                Heuriger heuriger;

                for (int i = 0; i < jArray.length(); i++) {
                    final JSONObject jsonData = jArray.getJSONObject(i);

                    final Dao<City, Integer> cityDao = helper.getDao(City.class);
                    Integer idOfCity = NumberConverter.getIntegerValueOfString(
                            OnlineProxy.getNotNullStringFromJSONObject(jsonData, Heuriger.CITY_COLUMN));
                    City cityOfHeurigen = cityDao.queryForId(idOfCity != 189 ? idOfCity : 188);

                    heuriger = OnlineProxy.parseHeurigerObjectFromJSONData(jsonData, cityOfHeurigen);

                    final Dao<Heuriger, Integer> heurigerDao = helper.getDao(Heuriger.class);
                    Log.i(TAG, "heuriger with id " + heuriger.getId() + " is about to be inserted/updated!");

                    if (heuriger.getName().equalsIgnoreCase("xxx"))
                        heurigerDao.delete(heuriger);
                    else
                        heurigerDao.createOrUpdate(heuriger);

                    Log.i(TAG, "heuriger with id " + heuriger.getId() + " saved!");
                }
            } else
                Log.e(TAG, "Returned objectJSON is null!");
        } catch (final JSONException e) {
            Log.e(TAG, "Error parsing data " + e.toString());
        } catch (final SQLException e) {
            Log.e(TAG, e.getMessage());
            e.printStackTrace();
        }
    }

    public void getNewAndUpdatedCalendarData() {

        prepareRestClientAndCallWebServiceWithLastUpdateDateAttached(RestClient.GET_NEW_AND_UPDATED_CALENDAR,
                RestClient.GET);

        try {
            if (currentRestClient.getObjectJson() != null) {
                final JSONArray jArray = currentRestClient.getObjectJson();

                Dao<OpenTime, Integer> openTimeDao = helper.getDao(OpenTime.class);
                Dao<OpeningCalendar, Integer> calendarDao = helper.getDao(OpeningCalendar.class);
                Dao<OpenDay, Integer> openDayDao = helper.getDao(OpenDay.class);

                for (int i = 0; i < jArray.length(); i++) {
                    final JSONObject jsonData = jArray.getJSONObject(i);

                    OpenTime openTime = openTimeDao
                            .queryForId(NumberConverter.getIntegerValueOfString(jsonData.getString("id")));

                    if (openTime == null) {
                        openTime = new OpenTime(NumberConverter.getIntegerValueOfString(jsonData.getString("id")),
                                DateAndTimeConverter.getTimeValueOfString(jsonData.getString("ot_start")),
                                DateAndTimeConverter.getTimeValueOfString(jsonData.getString("ot_end")));

                        openTimeDao.createOrUpdate(openTime);
                    }

                    OpeningCalendar calendar = calendarDao
                            .queryForId(NumberConverter.getIntegerValueOfString(jsonData.getString("c_id")));

                    if (calendar == null) {
                        calendar = new OpeningCalendar(
                                NumberConverter.getIntegerValueOfString(jsonData.getString("c_id")),
                                new Heuriger(
                                        NumberConverter.getIntegerValueOfString(jsonData.getString("id_heuriger"))),
                                DateAndTimeConverter.getFileDateValueOfString(jsonData.getString("c_start")),
                                DateAndTimeConverter.getFileDateValueOfString(jsonData.getString("c_end")));

                        calendarDao.createOrUpdate(calendar);
                    }

                    OpenDay openDay = new OpenDay(
                            NumberConverter.getIntegerValueOfString(jsonData.getString("od_id")), calendar,
                            openTime, NumberConverter.getIntegerValueOfString(jsonData.getString("day")));

                    openDayDao.createOrUpdate(openDay);
                }
            } else
                Log.e(TAG, "Returned objectJSON is null!");
        } catch (final JSONException e) {
            Log.e(TAG, "Error parsing data " + e.toString());
            e.printStackTrace();
        } catch (final SQLException e) {
            Log.e(TAG, e.getMessage());
            e.printStackTrace();
        }
    }

    private void prepareRestClientAndCallWebServiceWithLastUpdateDateAttached(final String service,
            int requestType) {
        String lastUpdateString = PreferencesActivity.getStringPreference(R.string.last_database_update_key, null);

        prepareRestClientAndCallWebService(service + lastUpdateString, requestType);
    }

    private void prepareRestClientAndCallWebService(final String service, int requestType) {
        if (currentRestClient == null)
            currentRestClient = new RestClient(service);
        if (!currentRestClient.getService().equals(service))
            currentRestClient.setService(service);
        try {
            currentRestClient.callWebService(requestType);
        } catch (final IllegalStateException e1) {
            e1.printStackTrace();
        } catch (final ClientProtocolException e1) {
            e1.printStackTrace();
        } catch (final IOException e1) {
            e1.printStackTrace();
        }
    }

    /**
     * Calculate elapsed time of any action.
     * Save a a timestamp (eg. new Date()) before starting the action and call this method afterwards.
     * 
     * @param start the timestamp before the action started
     * @return elapsed time as string, format 'hh:mm:ss' or 'mm:ss' depending on duration was > 1 hour and with leading zeros
     */
    public static String calculateElapsedTime(final Date start) {
        final Date stop = new Date();
        Long diff = stop.getTime() - start.getTime();

        final long secondInMillis = 1000;
        final long minuteInMillis = secondInMillis * 60;
        final long hourInMillis = minuteInMillis * 60;

        final long elapsedHours = diff / hourInMillis;

        diff = diff % hourInMillis;
        final long elapsedMinutes = diff / minuteInMillis;

        diff = diff % minuteInMillis;
        final long elapsedSeconds = diff / secondInMillis;

        if (elapsedHours != 0)
            return NumberConverter.addLeadingZeroToLong(elapsedHours) + ":"
                    + NumberConverter.addLeadingZeroToLong(elapsedMinutes) + ":"
                    + NumberConverter.addLeadingZeroToLong(elapsedSeconds);
        return NumberConverter.addLeadingZeroToLong(elapsedMinutes) + ":"
                + NumberConverter.addLeadingZeroToLong(elapsedSeconds);
    }

    public OfflineProxy getOfflineProxy() {
        if (offlineProxy == null)
            offlineProxy = new OfflineProxy();
        return offlineProxy;
    }
}