Reimport exported CSV files

pull/563/head
Lasse Lindgård 6 years ago
parent 13f4981066
commit 4cfb14cb7f

@ -41,7 +41,8 @@ public class GenericImporter extends AbstractImporter
@NonNull LoopDBImporter loopDBImporter,
@NonNull RewireDBImporter rewireDBImporter,
@NonNull TickmateDBImporter tickmateDBImporter,
@NonNull HabitBullCSVImporter habitBullCSVImporter)
@NonNull HabitBullCSVImporter habitBullCSVImporter,
@NonNull HabitsCSVImporter habitsCSVImporter)
{
super(habits);
importers = new LinkedList<>();
@ -49,6 +50,7 @@ public class GenericImporter extends AbstractImporter
importers.add(rewireDBImporter);
importers.add(tickmateDBImporter);
importers.add(habitBullCSVImporter);
importers.add(habitsCSVImporter);
}
@Override

@ -0,0 +1,162 @@
package org.isoron.uhabits.core.io;
import androidx.annotation.NonNull;
import com.opencsv.CSVReader;
import org.isoron.uhabits.core.models.Checkmark;
import org.isoron.uhabits.core.models.Frequency;
import org.isoron.uhabits.core.models.Habit;
import org.isoron.uhabits.core.models.HabitList;
import org.isoron.uhabits.core.models.ModelFactory;
import org.isoron.uhabits.core.models.Timestamp;
import org.isoron.uhabits.core.utils.ColorConstants;
import org.isoron.uhabits.core.utils.DateFormats;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.inject.Inject;
public class HabitsCSVImporter extends AbstractImporter {
private ModelFactory modelFactory;
@Inject
public HabitsCSVImporter(@NonNull HabitList habits,
@NonNull ModelFactory modelFactory) {
super(habits);
this.modelFactory = modelFactory;
}
@Override
public boolean canHandle(@NonNull File file) {
try {
ZipFile zipFile = new ZipFile(file);
ZipEntry entry = zipFile.getEntry("Habits.csv");
return entry != null;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public void importHabitsFromFile(@NonNull File file) throws IOException {
ZipFile zipFile = new ZipFile(file);
CSVReader habitsCsv = new CSVReader(new InputStreamReader(zipFile.getInputStream(zipFile.getEntry("Habits.csv"))));
try {
HashMap<String, Habit> map = new HashMap<>();
boolean hasQuestion = false;
for (String line[] : habitsCsv) {
if ("Position".equals(line[0])) {
// older csv files did not have a question column
if ("Question".equals(line[2])) hasQuestion = true;
continue;
}
int idx = 0;
String position = line[idx++];
String name = line[idx++];
String question = hasQuestion ? line[idx++] : null;
String desc = line[idx++];
int reps = Integer.parseInt(line[idx++]);
int intv = Integer.parseInt(line[idx++]);
String colr = line[idx++];
Habit habit = findExisting(name);
if (habit == null) {
habit = modelFactory.buildHabit();
habit.setName(name);
if (hasQuestion) {
habit.setDescription(desc);
habit.setQuestion(question);
} else {
habit.setDescription("");
habit.setQuestion(desc);
}
habit.setFrequency(new Frequency(reps, intv));
habit.setColor(findColor(colr));
habitList.add(habit);
}
parseCheckmarks(findCheckmarks(position, zipFile), habit);
}
} finally {
try {
zipFile.close();
habitsCsv.close();
} catch (IOException e) {
// ignore
}
}
}
Timestamp parse(String ts) throws ParseException {
Date date = DateFormats.getCSVDateFormat().parse(ts);
Timestamp timestamp = new Timestamp(date.getTime());
return timestamp;
}
void parseCheckmarks(CSVReader checkmarks, Habit habit) {
if (checkmarks == null) return;
try {
for (String line[] : checkmarks) {
try {
Timestamp ts = parse(line[0]);
int value = Integer.parseInt(line[1]);
// only add positive changes ;)
if (value > Checkmark.UNCHECKED) {
habit.getRepetitions().toggle(ts, value);
}
} catch (Exception e) {
// skip
}
}
} finally {
try {
checkmarks.close();
} catch (IOException e) {
// ignore
}
}
}
CSVReader findCheckmarks(String position, ZipFile zipFile) throws IOException {
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
// look for 00x */Checkmarks.csv
if (!entry.isDirectory() && entry.getName().startsWith(position) && entry.getName().endsWith("/Checkmarks.csv")) {
return new CSVReader(new InputStreamReader(zipFile.getInputStream(entry)));
}
}
return null;
}
private Habit findExisting(String name) {
Iterator<Habit> iterator = habitList.iterator();
while (iterator.hasNext()) {
Habit habit = iterator.next();
if (habit.getName().equals(name)) return habit;
}
return null;
}
private int findColor(String hex) {
for (int i = 0; i < ColorConstants.CSV_PALETTE.length; i++) {
if (ColorConstants.CSV_PALETTE[i].equalsIgnoreCase(hex)) {
return i;
}
}
return 0;
}
}

@ -19,20 +19,33 @@
package org.isoron.uhabits.core.io;
import org.apache.commons.io.*;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.junit.*;
import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.zip.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.isoron.uhabits.core.BaseUnitTest;
import org.isoron.uhabits.core.models.Habit;
import org.isoron.uhabits.core.models.HabitList;
import org.isoron.uhabits.core.models.memory.MemoryModelFactory;
import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.spy;
public class HabitsCSVExporterTest extends BaseUnitTest
public class HabitsCSVExporterAndImporterTest extends BaseUnitTest
{
private File baseDir;
@ -77,6 +90,39 @@ public class HabitsCSVExporterTest extends BaseUnitTest
assertPathExists("Scores.csv");
}
@Test
public void testImportCSV() throws IOException {
List<Habit> selected = new LinkedList<>();
for (Habit h : habitList) selected.add(h);
HabitsCSVExporter exporter =
new HabitsCSVExporter(habitList, selected, baseDir);
File file = new File(exporter.writeArchive());
HabitList oldHabits = habitList;
// reset model before importing
modelFactory = new MemoryModelFactory();
habitList = spy(modelFactory.buildHabitList());
HabitsCSVImporter importer = new HabitsCSVImporter(habitList, modelFactory);
assertTrue(importer.canHandle(file));
importer.importHabitsFromFile(file);
String fixed = stringRepresentation(oldHabits);
String updated = stringRepresentation(habitList);
// equals methods are too strict for this purpose
assertEquals(fixed, updated);
}
@NotNull
private String stringRepresentation(HabitList oldHabits) {
assertEquals(2, oldHabits.size());
return oldHabits.getByPosition(0).toString() + oldHabits.getByPosition(1).toString();
}
private void unzip(File file) throws IOException
{
ZipFile zip = new ZipFile(file);

@ -135,7 +135,8 @@ public class ImportTest extends BaseUnitTest
new LoopDBImporter(habitList, modelFactory, databaseOpener),
new RewireDBImporter(habitList, modelFactory, databaseOpener),
new TickmateDBImporter(habitList, modelFactory, databaseOpener),
new HabitBullCSVImporter(habitList, modelFactory));
new HabitBullCSVImporter(habitList, modelFactory),
new HabitsCSVImporter(habitList, modelFactory));
assertTrue(importer.canHandle(file));
importer.importHabitsFromFile(file);

Loading…
Cancel
Save