Convert some core.io classes to Kotlin

pull/699/head
Alinson S. Xavier 5 years ago
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))
}
}
}

@ -30,4 +30,29 @@ interface Logger {
fun debug(msg: String)
fun error(msg: String)
fun error(exception: Exception)
}
class StandardLogging : Logging {
override fun getLogger(name: String): Logger {
return StandardLogger(name)
}
}
class StandardLogger(val name: String): Logger {
override fun info(msg: String) {
println("[$name] $msg")
}
override fun debug(msg: String) {
println("[$name] $msg")
}
override fun error(msg: String) {
println("[$name] $msg")
}
override fun error(exception: Exception) {
exception.printStackTrace()
}
}

@ -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()
}
}

@ -134,7 +134,7 @@ public class ImportTest extends BaseUnitTest
assertTrue(file.canRead());
GenericImporter importer = new GenericImporter(habitList,
new LoopDBImporter(habitList, modelFactory, databaseOpener, commandRunner),
new LoopDBImporter(habitList, modelFactory, databaseOpener, commandRunner, new StandardLogging()),
new RewireDBImporter(habitList, modelFactory, databaseOpener),
new TickmateDBImporter(habitList, modelFactory, databaseOpener),
new HabitBullCSVImporter(habitList, modelFactory));

Loading…
Cancel
Save