/* * Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com> * * This file is part of Loop Habit Tracker. * * Loop Habit Tracker 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. * * Loop Habit Tracker 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 org.isoron.uhabits.io; import android.database.*; import android.database.sqlite.*; import android.support.annotation.*; import org.isoron.uhabits.models.*; import org.isoron.uhabits.utils.DatabaseUtils; import org.isoron.uhabits.utils.*; import java.io.*; import java.util.*; import javax.inject.*; import static android.database.sqlite.SQLiteDatabase.*; /** * Class that imports database files exported by Rewire. */ public class RewireDBImporter extends AbstractImporter { private ModelFactory modelFactory; @Inject public RewireDBImporter(@NonNull HabitList habits, @NonNull ModelFactory modelFactory) { super(habits); this.modelFactory = modelFactory; } @Override public boolean canHandle(@NonNull File file) throws IOException { if (!isSQLite3File(file)) return false; SQLiteDatabase db = openDatabase(file.getPath(), null, OPEN_READONLY); Cursor c = db.rawQuery( "select count(*) from SQLITE_MASTER where name=? or name=?", new String[]{ "CHECKINS", "UNIT" }); boolean result = (c.moveToFirst() && c.getInt(0) == 2); c.close(); db.close(); return result; } @Override public void importHabitsFromFile(@NonNull File file) throws IOException { String path = file.getPath(); final SQLiteDatabase db = openDatabase(path, null, OPEN_READONLY); DatabaseUtils.executeAsTransaction(() -> createHabits(db)); db.close(); } private void createCheckmarks(@NonNull SQLiteDatabase db, @NonNull Habit habit, int rewireHabitId) { Cursor c = null; try { String[] params = { Integer.toString(rewireHabitId) }; c = db.rawQuery( "select distinct date from checkins where habit_id=? and type=2", params); if (!c.moveToFirst()) return; do { String date = c.getString(0); int year = Integer.parseInt(date.substring(0, 4)); int month = Integer.parseInt(date.substring(4, 6)); int day = Integer.parseInt(date.substring(6, 8)); GregorianCalendar cal = DateUtils.getStartOfTodayCalendar(); cal.set(year, month - 1, day); habit.getRepetitions().toggleTimestamp(cal.getTimeInMillis()); } while (c.moveToNext()); } finally { if (c != null) c.close(); } } private void createHabits(SQLiteDatabase db) { Cursor c = null; try { c = db.rawQuery( "select _id, name, description, schedule, active_days, " + "repeating_count, days, period from habits", new String[0]); if (!c.moveToFirst()) return; do { int id = c.getInt(0); String name = c.getString(1); String description = c.getString(2); int schedule = c.getInt(3); String activeDays = c.getString(4); int repeatingCount = c.getInt(5); int days = c.getInt(6); int periodIndex = c.getInt(7); Habit habit = modelFactory.buildHabit(); habit.setName(name); habit.setDescription(description); int periods[] = { 7, 31, 365 }; int numerator, denominator; switch (schedule) { case 0: numerator = activeDays.split(",").length; denominator = 7; break; case 1: numerator = days; denominator = (periods[periodIndex]); break; case 2: numerator = 1; denominator = repeatingCount; break; default: throw new IllegalStateException(); } habit.setFrequency(new Frequency(numerator, denominator)); habits.add(habit); createReminder(db, habit, id); createCheckmarks(db, habit, id); } while (c.moveToNext()); } finally { if (c != null) c.close(); } } private void createReminder(SQLiteDatabase db, Habit habit, int rewireHabitId) { String[] params = { Integer.toString(rewireHabitId) }; Cursor c = null; try { c = db.rawQuery( "select time, active_days from reminders where habit_id=? limit 1", params); if (!c.moveToFirst()) return; int rewireReminder = Integer.parseInt(c.getString(0)); if (rewireReminder <= 0 || rewireReminder >= 1440) return; boolean reminderDays[] = new boolean[7]; String activeDays[] = c.getString(1).split(","); for (String d : activeDays) { int idx = (Integer.parseInt(d) + 1) % 7; reminderDays[idx] = true; } int hour = rewireReminder / 60; int minute = rewireReminder % 60; WeekdayList days = new WeekdayList(reminderDays); Reminder reminder = new Reminder(hour, minute, days); habit.setReminder(reminder); habits.update(habit); } finally { if (c != null) c.close(); } } }