mirror of https://github.com/iSoron/uhabits.git
parent
a02c7bdc44
commit
298bb01762
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Á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.core.io;
|
||||
|
||||
import androidx.annotation.*;
|
||||
|
||||
import org.isoron.uhabits.core.models.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import javax.inject.*;
|
||||
|
||||
/**
|
||||
* A GenericImporter decides which implementation of AbstractImporter is able to
|
||||
* handle a given file and delegates to it the task of importing the data.
|
||||
*/
|
||||
public class GenericImporter extends AbstractImporter
|
||||
{
|
||||
List<AbstractImporter> importers;
|
||||
|
||||
@Inject
|
||||
public GenericImporter(@NonNull HabitList habits,
|
||||
@NonNull LoopDBImporter loopDBImporter,
|
||||
@NonNull RewireDBImporter rewireDBImporter,
|
||||
@NonNull TickmateDBImporter tickmateDBImporter,
|
||||
@NonNull HabitBullCSVImporter habitBullCSVImporter)
|
||||
{
|
||||
super(habits);
|
||||
importers = new LinkedList<>();
|
||||
importers.add(loopDBImporter);
|
||||
importers.add(rewireDBImporter);
|
||||
importers.add(tickmateDBImporter);
|
||||
importers.add(habitBullCSVImporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHandle(@NonNull File file) throws IOException
|
||||
{
|
||||
for (AbstractImporter importer : importers)
|
||||
if (importer.canHandle(file)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void importHabitsFromFile(@NonNull File file) throws IOException
|
||||
{
|
||||
for (AbstractImporter importer : importers)
|
||||
if (importer.canHandle(file)) importer.importHabitsFromFile(file);
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Á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.core.io
|
||||
|
||||
import org.isoron.uhabits.core.models.*
|
||||
import java.io.*
|
||||
import javax.inject.*
|
||||
|
||||
/**
|
||||
* A GenericImporter decides which implementation of AbstractImporter is able to
|
||||
* handle a given file and delegates to it the task of importing the data.
|
||||
*/
|
||||
class GenericImporter
|
||||
@Inject constructor(
|
||||
habits: HabitList,
|
||||
loopDBImporter: LoopDBImporter,
|
||||
rewireDBImporter: RewireDBImporter,
|
||||
tickmateDBImporter: TickmateDBImporter,
|
||||
habitBullCSVImporter: HabitBullCSVImporter,
|
||||
) : AbstractImporter(habits) {
|
||||
|
||||
var importers: List<AbstractImporter> = listOf(
|
||||
loopDBImporter,
|
||||
rewireDBImporter,
|
||||
tickmateDBImporter,
|
||||
habitBullCSVImporter,
|
||||
)
|
||||
|
||||
override fun canHandle(file: File): Boolean {
|
||||
for (importer in importers) {
|
||||
if (importer.canHandle(file)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun importHabitsFromFile(file: File) {
|
||||
for (importer in importers) {
|
||||
if (importer.canHandle(file)) {
|
||||
importer.importHabitsFromFile(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Á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.core.io;
|
||||
|
||||
import androidx.annotation.*;
|
||||
|
||||
import com.opencsv.*;
|
||||
|
||||
import org.isoron.uhabits.core.models.*;
|
||||
import org.isoron.uhabits.core.utils.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import javax.inject.*;
|
||||
|
||||
import static org.isoron.uhabits.core.models.Entry.*;
|
||||
|
||||
|
||||
/**
|
||||
* Class that imports data from HabitBull CSV files.
|
||||
*/
|
||||
public class HabitBullCSVImporter extends AbstractImporter
|
||||
{
|
||||
private ModelFactory modelFactory;
|
||||
|
||||
@Inject
|
||||
public HabitBullCSVImporter(@NonNull HabitList habits,
|
||||
@NonNull ModelFactory modelFactory)
|
||||
{
|
||||
super(habits);
|
||||
this.modelFactory = modelFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHandle(@NonNull File file) throws IOException
|
||||
{
|
||||
BufferedReader reader = new BufferedReader(new FileReader(file));
|
||||
String line = reader.readLine();
|
||||
return line.startsWith("HabitName,HabitDescription,HabitCategory");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void importHabitsFromFile(@NonNull final File file)
|
||||
throws IOException
|
||||
{
|
||||
CSVReader reader = new CSVReader(new FileReader(file));
|
||||
HashMap<String, Habit> map = new HashMap<>();
|
||||
|
||||
for (String line[] : reader)
|
||||
{
|
||||
String name = line[0];
|
||||
if (name.equals("HabitName")) continue;
|
||||
|
||||
String description = line[1];
|
||||
String dateString[] = line[3].split("-");
|
||||
int year = Integer.parseInt(dateString[0]);
|
||||
int month = Integer.parseInt(dateString[1]);
|
||||
int day = Integer.parseInt(dateString[2]);
|
||||
|
||||
Calendar date = DateUtils.getStartOfTodayCalendar();
|
||||
date.set(year, month - 1, day);
|
||||
|
||||
Timestamp timestamp = new Timestamp(date.getTimeInMillis());
|
||||
|
||||
int value = Integer.parseInt(line[4]);
|
||||
if (value != 1) continue;
|
||||
|
||||
Habit h = map.get(name);
|
||||
|
||||
if (h == null)
|
||||
{
|
||||
h = modelFactory.buildHabit();
|
||||
h.setName(name);
|
||||
h.setDescription(description == null ? "" : description);
|
||||
h.setFrequency(Frequency.DAILY);
|
||||
habitList.add(h);
|
||||
map.put(name, h);
|
||||
}
|
||||
|
||||
h.getOriginalEntries().add(new Entry(timestamp, YES_MANUAL));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Á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.core.io
|
||||
|
||||
import com.opencsv.*
|
||||
import org.isoron.uhabits.core.models.*
|
||||
import org.isoron.uhabits.core.utils.*
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
import javax.inject.*
|
||||
|
||||
/**
|
||||
* Class that imports data from HabitBull CSV files.
|
||||
*/
|
||||
class HabitBullCSVImporter
|
||||
@Inject constructor(
|
||||
habits: HabitList,
|
||||
private val modelFactory: ModelFactory,
|
||||
) : AbstractImporter(habits) {
|
||||
|
||||
override fun canHandle(file: File): Boolean {
|
||||
val reader = BufferedReader(FileReader(file))
|
||||
val line = reader.readLine()
|
||||
return line.startsWith("HabitName,HabitDescription,HabitCategory")
|
||||
}
|
||||
|
||||
override fun importHabitsFromFile(file: File) {
|
||||
val reader = CSVReader(FileReader(file))
|
||||
val map = HashMap<String, Habit>()
|
||||
for (line in reader) {
|
||||
val name = line[0]
|
||||
if (name == "HabitName") continue
|
||||
val description = line[1]
|
||||
val dateString = line[3].split("-").toTypedArray()
|
||||
val year = dateString[0].toInt()
|
||||
val month = dateString[1].toInt()
|
||||
val day = dateString[2].toInt()
|
||||
val date = DateUtils.getStartOfTodayCalendar()
|
||||
date[year, month - 1] = day
|
||||
val timestamp = Timestamp(date.timeInMillis)
|
||||
val value = line[4].toInt()
|
||||
if (value != 1) continue
|
||||
var h = map[name]
|
||||
if (h == null) {
|
||||
h = modelFactory.buildHabit()
|
||||
h.name = name
|
||||
h.description = description ?: ""
|
||||
h.frequency = Frequency.DAILY
|
||||
habitList.add(h)
|
||||
map[name] = h
|
||||
}
|
||||
h.originalEntries.add(Entry(timestamp, Entry.YES_MANUAL))
|
||||
}
|
||||
}
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Á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.core.io;
|
||||
|
||||
import androidx.annotation.*;
|
||||
|
||||
import org.isoron.uhabits.core.*;
|
||||
import org.isoron.uhabits.core.commands.*;
|
||||
import org.isoron.uhabits.core.database.*;
|
||||
import org.isoron.uhabits.core.models.*;
|
||||
import org.isoron.uhabits.core.models.sqlite.records.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import javax.inject.*;
|
||||
|
||||
import static org.isoron.uhabits.core.ConstantsKt.*;
|
||||
|
||||
/**
|
||||
* Class that imports data from database files exported by Loop Habit Tracker.
|
||||
*/
|
||||
public class LoopDBImporter extends AbstractImporter
|
||||
{
|
||||
@NonNull
|
||||
private final ModelFactory modelFactory;
|
||||
|
||||
@NonNull
|
||||
private final DatabaseOpener opener;
|
||||
@NonNull
|
||||
private final CommandRunner runner;
|
||||
|
||||
@Inject
|
||||
public LoopDBImporter(@AppScope @NonNull HabitList habitList,
|
||||
@AppScope @NonNull ModelFactory modelFactory,
|
||||
@AppScope @NonNull DatabaseOpener opener,
|
||||
@AppScope @NonNull CommandRunner runner)
|
||||
{
|
||||
super(habitList);
|
||||
this.modelFactory = modelFactory;
|
||||
this.opener = opener;
|
||||
this.runner = runner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHandle(@NonNull File file) throws IOException
|
||||
{
|
||||
if (!isSQLite3File(file)) return false;
|
||||
|
||||
Database db = opener.open(file);
|
||||
boolean canHandle = true;
|
||||
|
||||
Cursor c = db.query("select count(*) from SQLITE_MASTER " +
|
||||
"where name='Habits' or name='Repetitions'");
|
||||
|
||||
if (!c.moveToNext() || c.getInt(0) != 2)
|
||||
{
|
||||
// Log.w("LoopDBImporter", "Cannot handle file: tables not found");
|
||||
canHandle = false;
|
||||
}
|
||||
|
||||
if (db.getVersion() > DATABASE_VERSION)
|
||||
{
|
||||
// Log.w("LoopDBImporter", String.format(
|
||||
// "Cannot handle file: incompatible version: %d > %d",
|
||||
// db.getVersion(), DATABASE_VERSION));
|
||||
canHandle = false;
|
||||
}
|
||||
|
||||
c.close();
|
||||
db.close();
|
||||
return canHandle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void importHabitsFromFile(@NonNull File file)
|
||||
{
|
||||
Database db = opener.open(file);
|
||||
MigrationHelper helper = new MigrationHelper(db);
|
||||
helper.migrateTo(DATABASE_VERSION);
|
||||
|
||||
Repository<HabitRecord> habitsRepository;
|
||||
Repository<EntryRecord> entryRepository;
|
||||
habitsRepository = new Repository<>(HabitRecord.class, db);
|
||||
entryRepository = new Repository<>(EntryRecord.class, db);
|
||||
|
||||
List<HabitRecord> habitRecords = habitsRepository.findAll("order by position");
|
||||
for (HabitRecord habitRecord : habitRecords)
|
||||
{
|
||||
List<EntryRecord> entryRecords =
|
||||
entryRepository.findAll("where habit = ?",
|
||||
habitRecord.id.toString());
|
||||
|
||||
Habit habit = habitList.getByUUID(habitRecord.uuid);
|
||||
Command command;
|
||||
if (habit == null)
|
||||
{
|
||||
habit = modelFactory.buildHabit();
|
||||
habitRecord.id = null;
|
||||
habitRecord.copyTo(habit);
|
||||
command = new CreateHabitCommand(modelFactory, habitList, habit);
|
||||
command.run();
|
||||
}
|
||||
else
|
||||
{
|
||||
Habit modified = modelFactory.buildHabit();
|
||||
habitRecord.id = habit.getId();
|
||||
habitRecord.copyTo(modified);
|
||||
command = new EditHabitCommand(habitList, habit.getId(), modified);
|
||||
command.run();
|
||||
}
|
||||
|
||||
// Reload saved version of the habit
|
||||
habit = habitList.getByUUID(habitRecord.uuid);
|
||||
|
||||
for (EntryRecord r : entryRecords)
|
||||
{
|
||||
Timestamp t = new Timestamp(r.timestamp);
|
||||
Entry existingEntry = habit.getOriginalEntries().get(t);
|
||||
if (existingEntry.getValue() != r.value)
|
||||
new CreateRepetitionCommand(habitList, habit, t, r.value).run();
|
||||
}
|
||||
|
||||
runner.notifyListeners(command);
|
||||
}
|
||||
db.close();
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Á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.core.io
|
||||
|
||||
import org.isoron.uhabits.core.*
|
||||
import org.isoron.uhabits.core.commands.*
|
||||
import org.isoron.uhabits.core.database.*
|
||||
import org.isoron.uhabits.core.models.*
|
||||
import org.isoron.uhabits.core.models.sqlite.records.*
|
||||
import java.io.*
|
||||
import javax.inject.*
|
||||
|
||||
/**
|
||||
* Class that imports data from database files exported by Loop Habit Tracker.
|
||||
*/
|
||||
class LoopDBImporter
|
||||
@Inject constructor(
|
||||
@AppScope val habitList: HabitList,
|
||||
@AppScope val modelFactory: ModelFactory,
|
||||
@AppScope val opener: DatabaseOpener,
|
||||
@AppScope val runner: CommandRunner,
|
||||
@AppScope logging: Logging,
|
||||
) : AbstractImporter(habitList) {
|
||||
|
||||
private val logger = logging.getLogger("LoopDBImporter")
|
||||
|
||||
override fun canHandle(file: File): Boolean {
|
||||
if (!isSQLite3File(file)) return false
|
||||
val db = opener.open(file)!!
|
||||
var canHandle = true
|
||||
val c = db.query("select count(*) from SQLITE_MASTER where name='Habits' or name='Repetitions'")
|
||||
if (!c.moveToNext() || c.getInt(0) != 2) {
|
||||
logger.error("Cannot handle file: tables not found")
|
||||
canHandle = false
|
||||
}
|
||||
if (db.version > DATABASE_VERSION) {
|
||||
logger.error("Cannot handle file: incompatible version: ${db.version} > $DATABASE_VERSION")
|
||||
canHandle = false
|
||||
}
|
||||
c.close()
|
||||
db.close()
|
||||
return canHandle
|
||||
}
|
||||
|
||||
override fun importHabitsFromFile(file: File) {
|
||||
val db = opener.open(file)!!
|
||||
val helper = MigrationHelper(db)
|
||||
helper.migrateTo(DATABASE_VERSION)
|
||||
|
||||
val habitsRepository = Repository(HabitRecord::class.java, db)
|
||||
val entryRepository = Repository(EntryRecord::class.java, db)
|
||||
|
||||
for (habitRecord in habitsRepository.findAll("order by position")) {
|
||||
var habit = habitList.getByUUID(habitRecord.uuid)
|
||||
val entryRecords = entryRepository.findAll("where habit = ?", habitRecord.id.toString())
|
||||
|
||||
var command: Command
|
||||
if (habit == null) {
|
||||
habit = modelFactory.buildHabit()
|
||||
habitRecord.id = null
|
||||
habitRecord.copyTo(habit)
|
||||
command = CreateHabitCommand(modelFactory, habitList, habit)
|
||||
command.run()
|
||||
} else {
|
||||
val modified = modelFactory.buildHabit()
|
||||
habitRecord.id = habit.id
|
||||
habitRecord.copyTo(modified)
|
||||
command = EditHabitCommand(habitList, habit.id!!, modified)
|
||||
command.run()
|
||||
}
|
||||
|
||||
// Reload saved version of the habit
|
||||
habit = habitList.getByUUID(habitRecord.uuid)
|
||||
|
||||
for (r in entryRecords) {
|
||||
val t = Timestamp(r.timestamp)
|
||||
val (_, value) = habit!!.originalEntries.get(t)
|
||||
if (value != r.value) CreateRepetitionCommand(habitList, habit, t, r.value).run()
|
||||
}
|
||||
|
||||
runner.notifyListeners(command)
|
||||
}
|
||||
|
||||
db.close()
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in new issue