From 20f75a16f926b418128e9b86751dc983bfff98c6 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 6 Feb 2021 15:21:32 +0100 Subject: [PATCH 01/14] Refactoring: Rename method getAvailableDataYearMonth() --- .../whiterabbit/api/StorageService.java | 6 ++++++ .../whiterabbit/logic/model/MonthIndex.java | 2 +- .../vacation/VacationReportGenerator.java | 2 +- .../whiterabbit/logic/service/AppService.java | 2 +- .../logic/storage/CachingStorageImpl.java | 6 +++--- .../logic/storage/JsonFileStorage.java | 2 +- .../logic/storage/MonthIndexStorage.java | 6 +++--- .../whiterabbit/logic/storage/Storage.java | 2 +- .../logic/model/DayRecordTest.java | 2 +- .../logic/model/MonthIndexTest.java | 2 +- .../vacation/VacationReportGeneratorTest.java | 2 +- .../logic/service/ActivityServiceTest.java | 2 +- .../logic/storage/CachingStorageImplTest.java | 20 +++++++++---------- .../logic/storage/JsonFileStorageTest.java | 4 ++-- .../logic/storage/MonthIndexStorageTest.java | 4 ++-- 15 files changed, 35 insertions(+), 29 deletions(-) create mode 100644 api/src/main/java/org/itsallcode/whiterabbit/api/StorageService.java diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/StorageService.java b/api/src/main/java/org/itsallcode/whiterabbit/api/StorageService.java new file mode 100644 index 00000000..e50af177 --- /dev/null +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/StorageService.java @@ -0,0 +1,6 @@ +package org.itsallcode.whiterabbit.api; + +public interface StorageService +{ + +} diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java index 1f35581d..98b14ea4 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java @@ -31,7 +31,7 @@ private MonthIndex(JsonMonth record, Map days) this.days = days; } - public static MonthIndex create(ContractTermsService contractTerms, JsonMonth record, ProjectService projectService) + public static MonthIndex create(ContractTermsService contractTerms, ProjectService projectService, JsonMonth record) { final Map jsonDays = record.getDays().stream() .collect(toMap(JsonDay::getDate, Function.identity())); diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/report/vacation/VacationReportGenerator.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/report/vacation/VacationReportGenerator.java index 91aa8ad9..eb0ee679 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/report/vacation/VacationReportGenerator.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/report/vacation/VacationReportGenerator.java @@ -43,7 +43,7 @@ public VacationReport generateReport() private class Calculator { - final List availableDataYearMonth = storage.getAvailableDataYearMonth(); + final List availableDataYearMonth = storage.getAvailableDataMonths(); final Map monthData = availableDataYearMonth.stream() // .map(storage::loadMonth) // .map(Optional::orElseThrow) // diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java index 3bcaa2fd..024f4209 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java @@ -191,7 +191,7 @@ public List getRecords(YearMonth yearMonth) public List getAvailableDataYearMonth() { - return storage.getAvailableDataYearMonth(); + return storage.getAvailableDataMonths(); } public Optional getMonth(YearMonth yearMonth) diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorageImpl.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorageImpl.java index c2d2f8f8..114e18cb 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorageImpl.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorageImpl.java @@ -68,9 +68,9 @@ private MonthIndex updateCache(MonthIndex month) } @Override - public List getAvailableDataYearMonth() + public List getAvailableDataMonths() { - return delegateStorage.getAvailableDataYearMonth(); + return delegateStorage.getAvailableDataMonths(); } @Override @@ -95,7 +95,7 @@ void ensureLatestDaysCached(LocalDate maxAge) List getRequiredYearMonths(LocalDate maxAge) { final YearMonth oldestYearMonth = YearMonth.from(maxAge); - return delegateStorage.getAvailableDataYearMonth().stream() + return delegateStorage.getAvailableDataMonths().stream() .filter(month -> !month.isBefore(oldestYearMonth)) .collect(toList()); } diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/JsonFileStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/JsonFileStorage.java index aed94d00..80c40123 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/JsonFileStorage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/JsonFileStorage.java @@ -97,7 +97,7 @@ private void createDirectory(Path dir) } } - List getAvailableDataYearMonth() + List getAvailableDataMonths() { return dateToFileMapper.getAllYearMonths().sorted().collect(toList()); } diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java index 37687b84..aab54917 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java @@ -61,9 +61,9 @@ public MultiMonthIndex loadAll() } @Override - public List getAvailableDataYearMonth() + public List getAvailableDataMonths() { - return fileStorage.getAvailableDataYearMonth(); + return fileStorage.getAvailableDataMonths(); } private MonthIndex createNewMonth(YearMonth date) @@ -78,7 +78,7 @@ private MonthIndex createNewMonth(YearMonth date) private MonthIndex createMonthIndex(final JsonMonth jsonMonth) { - return MonthIndex.create(contractTerms, jsonMonth, projectService); + return MonthIndex.create(contractTerms, projectService, jsonMonth); } Duration loadPreviousMonthOvertime(YearMonth date) diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/Storage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/Storage.java index 011ad687..b1f1af50 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/Storage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/Storage.java @@ -17,6 +17,6 @@ public interface Storage MultiMonthIndex loadAll(); - List getAvailableDataYearMonth(); + List getAvailableDataMonths(); } \ No newline at end of file diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java index c55a74cf..c25c461b 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java @@ -433,7 +433,7 @@ private MonthIndex month(LocalDate date, Duration overtimePreviousMonth, JsonDay jsonMonth.setMonth(date.getMonth()); jsonMonth.setYear(date.getYear()); jsonMonth.setOvertimePreviousMonth(overtimePreviousMonth); - return MonthIndex.create(contractTerms(), jsonMonth, projectServiceMock); + return MonthIndex.create(contractTerms(), projectServiceMock, jsonMonth); } private void assertOvertime(LocalDate date, LocalTime begin, LocalTime end, Duration expectedOvertime) diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java index 32d1ac33..4d381679 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java @@ -207,6 +207,6 @@ private MonthIndex create(JsonMonth record) private MonthIndex create(Config config, JsonMonth record) { - return MonthIndex.create(new ContractTermsService(config), record, projectServiceMock); + return MonthIndex.create(new ContractTermsService(config), projectServiceMock, record); } } diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/report/vacation/VacationReportGeneratorTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/report/vacation/VacationReportGeneratorTest.java index f669d991..bd2cc007 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/report/vacation/VacationReportGeneratorTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/report/vacation/VacationReportGeneratorTest.java @@ -254,7 +254,7 @@ private void simulateMonths(MonthIndex... months) { final List availableDataYearMonth = Arrays.stream(months).map(MonthIndex::getYearMonth) .collect(toList()); - when(storageMock.getAvailableDataYearMonth()).thenReturn(availableDataYearMonth); + when(storageMock.getAvailableDataMonths()).thenReturn(availableDataYearMonth); for (final MonthIndex monthIndex : months) { diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ActivityServiceTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ActivityServiceTest.java index 6f2ba3d5..e96a5984 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ActivityServiceTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ActivityServiceTest.java @@ -130,6 +130,6 @@ private MonthIndex createMonth() monthRecord.setDays(new ArrayList<>()); monthRecord.setYear(DATE.getYear()); monthRecord.setMonth(DATE.getMonth()); - return MonthIndex.create(contractTermsServiceMock, monthRecord, projectService); + return MonthIndex.create(contractTermsServiceMock, projectService, monthRecord); } } diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/CachingStorageImplTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/CachingStorageImplTest.java index 81934975..1dbb03be 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/CachingStorageImplTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/CachingStorageImplTest.java @@ -99,7 +99,7 @@ void loadAll_doesNotUpdateCache_whenNoEntriesFound() @Test void getRequiredYearMonths_returnsEmptyList_whenNoDataAvailable() { - when(delegateStorageMock.getAvailableDataYearMonth()).thenReturn(emptyList()); + when(delegateStorageMock.getAvailableDataMonths()).thenReturn(emptyList()); assertThat(storage.getRequiredYearMonths(LocalDate.of(2020, Month.JANUARY, 1))).isEmpty(); } @@ -111,7 +111,7 @@ void getRequiredYearMonths_returnsRequiredMonths() final YearMonth february = YearMonth.of(2020, Month.FEBRUARY); final YearMonth march = YearMonth.of(2020, Month.MARCH); final YearMonth april = YearMonth.of(2020, Month.APRIL); - when(delegateStorageMock.getAvailableDataYearMonth()).thenReturn(List.of(january, february, march, april)); + when(delegateStorageMock.getAvailableDataMonths()).thenReturn(List.of(january, february, march, april)); assertThat(storage.getRequiredYearMonths(LocalDate.of(2020, Month.JANUARY, 1))) .containsExactly(january, february, march, april); @@ -124,7 +124,7 @@ void getRequiredYearMonths_includesMonthForLastDayOfTheMonth() final YearMonth february = YearMonth.of(2020, Month.FEBRUARY); final YearMonth march = YearMonth.of(2020, Month.MARCH); final YearMonth april = YearMonth.of(2020, Month.APRIL); - when(delegateStorageMock.getAvailableDataYearMonth()).thenReturn(List.of(january, february, march, april)); + when(delegateStorageMock.getAvailableDataMonths()).thenReturn(List.of(january, february, march, april)); assertThat(storage.getRequiredYearMonths(LocalDate.of(2020, Month.JANUARY, 31))) .containsExactly(january, february, march, april); @@ -137,7 +137,7 @@ void getRequiredYearMonths_omitsOlderMonths() final YearMonth february = YearMonth.of(2020, Month.FEBRUARY); final YearMonth march = YearMonth.of(2020, Month.MARCH); final YearMonth april = YearMonth.of(2020, Month.APRIL); - when(delegateStorageMock.getAvailableDataYearMonth()).thenReturn(List.of(january, february, march, april)); + when(delegateStorageMock.getAvailableDataMonths()).thenReturn(List.of(january, february, march, april)); assertThat(storage.getRequiredYearMonths(LocalDate.of(2020, Month.FEBRUARY, 1))) .containsExactly(february, march, april); @@ -148,7 +148,7 @@ void ensureLatestDaysCached_dataAvailable() { final YearMonth january = YearMonth.of(2020, Month.JANUARY); final YearMonth february = YearMonth.of(2020, Month.FEBRUARY); - when(delegateStorageMock.getAvailableDataYearMonth()).thenReturn(List.of(january, february)); + when(delegateStorageMock.getAvailableDataMonths()).thenReturn(List.of(january, february)); when(cacheMock.contains(january)).thenReturn(false); when(cacheMock.contains(february)).thenReturn(false); @@ -172,7 +172,7 @@ void ensureLatestDaysCached_dataAvailable_alreadyCached() { final YearMonth january = YearMonth.of(2020, Month.JANUARY); final YearMonth february = YearMonth.of(2020, Month.FEBRUARY); - when(delegateStorageMock.getAvailableDataYearMonth()).thenReturn(List.of(january, february)); + when(delegateStorageMock.getAvailableDataMonths()).thenReturn(List.of(january, february)); when(cacheMock.contains(january)).thenReturn(true); when(cacheMock.contains(february)).thenReturn(true); @@ -188,7 +188,7 @@ void ensureLatestDaysCached_cacheNotUpdatedWhenMonthNotFound() { final YearMonth january = YearMonth.of(2020, Month.JANUARY); final YearMonth february = YearMonth.of(2020, Month.FEBRUARY); - when(delegateStorageMock.getAvailableDataYearMonth()).thenReturn(List.of(january, february)); + when(delegateStorageMock.getAvailableDataMonths()).thenReturn(List.of(january, february)); when(delegateStorageMock.loadMonth(january)).thenReturn(Optional.empty()); when(delegateStorageMock.loadMonth(february)).thenReturn(Optional.empty()); @@ -204,7 +204,7 @@ void getLatestDays_delegatesToCache() final YearMonth january = YearMonth.of(2020, Month.JANUARY); final YearMonth february = YearMonth.of(2020, Month.FEBRUARY); - when(delegateStorageMock.getAvailableDataYearMonth()).thenReturn(List.of(january, february)); + when(delegateStorageMock.getAvailableDataMonths()).thenReturn(List.of(january, february)); when(cacheMock.contains(january)).thenReturn(false); when(cacheMock.contains(february)).thenReturn(false); @@ -237,7 +237,7 @@ private void verifyListenerUpdated() void getAvailableDataYearMonth_delegates() { final List list = new ArrayList<>(); - when(delegateStorageMock.getAvailableDataYearMonth()).thenReturn(list); - assertThat(storage.getAvailableDataYearMonth()).isSameAs(list); + when(delegateStorageMock.getAvailableDataMonths()).thenReturn(list); + assertThat(storage.getAvailableDataMonths()).isSameAs(list); } } diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/JsonFileStorageTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/JsonFileStorageTest.java index 863c9f98..9ea51671 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/JsonFileStorageTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/JsonFileStorageTest.java @@ -53,14 +53,14 @@ void sortsAvailableYearMonths() final YearMonth january2020 = YearMonth.of(2020, Month.JANUARY); final YearMonth december2019 = YearMonth.of(2019, Month.DECEMBER); when(dateToFileMapperMock.getAllYearMonths()).thenReturn(Stream.of(april2020, january2020, december2019)); - assertThat(jsonFileStorage.getAvailableDataYearMonth()).containsExactly(december2019, january2020, april2020); + assertThat(jsonFileStorage.getAvailableDataMonths()).containsExactly(december2019, january2020, april2020); } @Test void returnsEmptyAvailableMonths() { when(dateToFileMapperMock.getAllYearMonths()).thenReturn(Stream.empty()); - assertThat(jsonFileStorage.getAvailableDataYearMonth()).isEmpty(); + assertThat(jsonFileStorage.getAvailableDataMonths()).isEmpty(); } @Test diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java index f010aa1a..3e0cf6cd 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java @@ -140,9 +140,9 @@ void loadAll_nonEmpty() void getAvailableDataYearMonth() { final List availableYearMonths = List.of(YEAR_MONTH); - when(fileStorageMock.getAvailableDataYearMonth()).thenReturn(availableYearMonths); + when(fileStorageMock.getAvailableDataMonths()).thenReturn(availableYearMonths); - assertThat(storage.getAvailableDataYearMonth()).isSameAs(availableYearMonths); + assertThat(storage.getAvailableDataMonths()).isSameAs(availableYearMonths); } private JsonMonth jsonMonth(YearMonth yearMonth, Duration overtimePreviousMonth) From 25bd150a83105c4519219ac3f040d9e4c720a6e0 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 6 Feb 2021 15:31:51 +0100 Subject: [PATCH 02/14] Refactoring: move file storage to separate package --- .../logic/storage/CachingStorage.java | 17 ++++---- .../logic/storage/MonthIndexStorage.java | 5 ++- .../storage/{ => data}/DateToFileMapper.java | 4 +- .../storage/{ => data}/JsonFileStorage.java | 41 +++++++++++-------- .../logic/storage/JsonFileStorageTest.java | 11 ++--- .../logic/storage/MonthIndexStorageTest.java | 12 +++--- .../{ => data}/DateToFileMapperTest.java | 3 +- 7 files changed, 51 insertions(+), 42 deletions(-) rename logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/{ => data}/DateToFileMapper.java (95%) rename logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/{ => data}/JsonFileStorage.java (89%) rename logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/{ => data}/DateToFileMapperTest.java (96%) diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java index 41b7b245..2d4da50e 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java @@ -1,23 +1,24 @@ package org.itsallcode.whiterabbit.logic.storage; -import org.itsallcode.whiterabbit.logic.model.DayRecord; -import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; -import org.itsallcode.whiterabbit.logic.service.project.ProjectService; +import java.nio.file.Path; +import java.time.LocalDate; +import java.util.List; import javax.json.bind.Jsonb; import javax.json.bind.JsonbBuilder; import javax.json.bind.JsonbConfig; -import java.nio.file.Path; -import java.time.LocalDate; -import java.util.List; + +import org.itsallcode.whiterabbit.logic.model.DayRecord; +import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; +import org.itsallcode.whiterabbit.logic.service.project.ProjectService; +import org.itsallcode.whiterabbit.logic.storage.data.JsonFileStorage; public interface CachingStorage extends Storage { static CachingStorage create(Path dataDir, ContractTermsService contractTerms, ProjectService projectService) { - final DateToFileMapper dateToFileMapper = new DateToFileMapper(dataDir); final Jsonb jsonb = JsonbBuilder.create(new JsonbConfig().withFormatting(true)); - final JsonFileStorage fileStorage = new JsonFileStorage(jsonb, dateToFileMapper); + final JsonFileStorage fileStorage = new JsonFileStorage(jsonb, dataDir); final MonthIndexStorage monthIndexStorage = new MonthIndexStorage(contractTerms, projectService, fileStorage); return new CachingStorageImpl(monthIndexStorage); } diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java index aab54917..5f46fd8b 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java @@ -16,6 +16,7 @@ import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; +import org.itsallcode.whiterabbit.logic.storage.data.JsonFileStorage; class MonthIndexStorage implements Storage { @@ -36,7 +37,7 @@ class MonthIndexStorage implements Storage @Override public Optional loadMonth(YearMonth date) { - return fileStorage.loadMonthRecord(date).map(this::createMonthIndex); + return fileStorage.loadMonth(date).map(this::createMonthIndex); } @Override @@ -49,7 +50,7 @@ public MonthIndex loadOrCreate(final YearMonth yearMonth) @Override public void storeMonth(MonthIndex month) { - fileStorage.writeToFile(month.getYearMonth(), month.getMonthRecord()); + fileStorage.store(month.getYearMonth(), month.getMonthRecord()); } @Override diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/DateToFileMapper.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/DateToFileMapper.java similarity index 95% rename from logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/DateToFileMapper.java rename to logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/DateToFileMapper.java index 663e4c65..7b301358 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/DateToFileMapper.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/DateToFileMapper.java @@ -1,4 +1,4 @@ -package org.itsallcode.whiterabbit.logic.storage; +package org.itsallcode.whiterabbit.logic.storage.data; import java.io.IOException; import java.io.UncheckedIOException; @@ -23,7 +23,7 @@ public class DateToFileMapper private final DateTimeFormatter formatter; private final Pattern fileNamePattern = Pattern.compile("^(\\d\\d\\d\\d)-(\\d\\d)\\.json$"); - DateToFileMapper(Path dataDir) + public DateToFileMapper(Path dataDir) { formatter = DateTimeFormatter.ofPattern("yyyy-MM", Locale.ENGLISH); this.dataDir = dataDir; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/JsonFileStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java similarity index 89% rename from logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/JsonFileStorage.java rename to logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java index 80c40123..2c6cb50e 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/JsonFileStorage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java @@ -1,4 +1,4 @@ -package org.itsallcode.whiterabbit.logic.storage; +package org.itsallcode.whiterabbit.logic.storage.data; import static java.util.Comparator.comparing; import static java.util.stream.Collectors.toList; @@ -28,26 +28,18 @@ public class JsonFileStorage private final Jsonb jsonb; private final DateToFileMapper dateToFileMapper; - JsonFileStorage(Jsonb jsonb, DateToFileMapper dateToFileMapper) + public JsonFileStorage(Jsonb jsonb, Path dataDir) { - this.jsonb = jsonb; - this.dateToFileMapper = dateToFileMapper; + this(jsonb, new DateToFileMapper(dataDir)); } - private JsonMonth loadFromFile(Path file) + JsonFileStorage(Jsonb jsonb, DateToFileMapper dateToFileMapper) { - LOG.trace("Reading file {}", file); - try (InputStream stream = Files.newInputStream(file)) - { - return jsonb.fromJson(stream, JsonMonth.class); - } - catch (final IOException e) - { - throw new UncheckedIOException("Error reading file " + file, e); - } + this.jsonb = jsonb; + this.dateToFileMapper = dateToFileMapper; } - Optional loadMonthRecord(YearMonth date) + public Optional loadMonth(YearMonth date) { final Path file = dateToFileMapper.getPathForDate(date); if (file.toFile().exists()) @@ -65,7 +57,20 @@ Optional loadMonthRecord(YearMonth date) return Optional.empty(); } - void writeToFile(YearMonth yearMonth, JsonMonth record) + private JsonMonth loadFromFile(Path file) + { + LOG.trace("Reading file {}", file); + try (InputStream stream = Files.newInputStream(file)) + { + return jsonb.fromJson(stream, JsonMonth.class); + } + catch (final IOException e) + { + throw new UncheckedIOException("Error reading file " + file, e); + } + } + + public void store(YearMonth yearMonth, JsonMonth record) { final Path file = dateToFileMapper.getPathForDate(yearMonth); LOG.trace("Write month {} to file {}", yearMonth, file); @@ -97,12 +102,12 @@ private void createDirectory(Path dir) } } - List getAvailableDataMonths() + public List getAvailableDataMonths() { return dateToFileMapper.getAllYearMonths().sorted().collect(toList()); } - List loadAll() + public List loadAll() { return dateToFileMapper.getAllFiles() .filter(file -> !file.getFileName().toString().equals(Config.PROJECTS_JSON)) diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/JsonFileStorageTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/JsonFileStorageTest.java index 9ea51671..cfcade75 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/JsonFileStorageTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/JsonFileStorageTest.java @@ -20,6 +20,7 @@ import javax.json.bind.JsonbConfig; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; +import org.itsallcode.whiterabbit.logic.storage.data.DateToFileMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -68,7 +69,7 @@ void loadMonthReturnsEmptyOptional_WhenLegacyFileDoesNotExist() { when(dateToFileMapperMock.getPathForDate(YEAR_MONTH)).thenReturn(tempDir.resolve("does-not-exist")); when(dateToFileMapperMock.getLegacyPathForDate(YEAR_MONTH)).thenReturn(tempDir.resolve("does-not-exist")); - assertThat(jsonFileStorage.loadMonthRecord(YEAR_MONTH)).isEmpty(); + assertThat(jsonFileStorage.loadMonth(YEAR_MONTH)).isEmpty(); } @Test @@ -80,7 +81,7 @@ void loadMonthReturnsMonth_WhenLegacyFileExists() throws IOException when(dateToFileMapperMock.getPathForDate(YEAR_MONTH)).thenReturn(tempDir.resolve("does-not-exist")); when(dateToFileMapperMock.getLegacyPathForDate(YEAR_MONTH)).thenReturn(file); - final Optional loadedMonth = jsonFileStorage.loadMonthRecord(YEAR_MONTH); + final Optional loadedMonth = jsonFileStorage.loadMonth(YEAR_MONTH); assertThat(loadedMonth).isNotEmpty(); assertThat(loadedMonth.get().getYear()).isEqualTo(2020); } @@ -93,7 +94,7 @@ void loadMonthReturnsMonth_WhenFileExists() throws IOException final Path file = writeTempFile(month); when(dateToFileMapperMock.getPathForDate(YEAR_MONTH)).thenReturn(file); - final Optional loadedMonth = jsonFileStorage.loadMonthRecord(YEAR_MONTH); + final Optional loadedMonth = jsonFileStorage.loadMonth(YEAR_MONTH); assertThat(loadedMonth).isNotEmpty(); assertThat(loadedMonth.get().getYear()).isEqualTo(2020); } @@ -106,7 +107,7 @@ void writeToFile_writesFile() throws IOException final JsonMonth month = new JsonMonth(); month.setYear(2020); - jsonFileStorage.writeToFile(YEAR_MONTH, month); + jsonFileStorage.store(YEAR_MONTH, month); assertThat(file).exists().hasContent("{\"year\":2020}"); } @@ -119,7 +120,7 @@ void writeToFile_createsDirectory() throws IOException final JsonMonth month = new JsonMonth(); month.setYear(2020); - jsonFileStorage.writeToFile(YEAR_MONTH, month); + jsonFileStorage.store(YEAR_MONTH, month); assertThat(file).exists().hasContent("{\"year\":2020}"); } diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java index 3e0cf6cd..f15e31eb 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java @@ -51,7 +51,7 @@ void setUp() @Test void loadPreviousMonthOvertime_returnsZero_whenNoPreviousMonth() { - when(fileStorageMock.loadMonthRecord(YearMonth.of(2020, Month.OCTOBER))).thenReturn(Optional.empty()); + when(fileStorageMock.loadMonth(YearMonth.of(2020, Month.OCTOBER))).thenReturn(Optional.empty()); assertThat(storage.loadPreviousMonthOvertime(YEAR_MONTH)).isZero(); } @@ -59,7 +59,7 @@ void loadPreviousMonthOvertime_returnsZero_whenNoPreviousMonth() @Test void loadPreviousMonthOvertime_returnsPreviousMonthOvertime() { - when(fileStorageMock.loadMonthRecord(PREVIOUS_MONTH)) + when(fileStorageMock.loadMonth(PREVIOUS_MONTH)) .thenReturn(Optional.of(jsonMonth(PREVIOUS_MONTH, Duration.ofMinutes(5)))); assertThat(storage.loadPreviousMonthOvertime(YEAR_MONTH)).hasMinutes(5); @@ -68,7 +68,7 @@ void loadPreviousMonthOvertime_returnsPreviousMonthOvertime() @Test void loadPreviousMonthOvertime_truncatesToMinute() { - when(fileStorageMock.loadMonthRecord(PREVIOUS_MONTH)) + when(fileStorageMock.loadMonth(PREVIOUS_MONTH)) .thenReturn(Optional.of(jsonMonth(PREVIOUS_MONTH, Duration.ofMinutes(5).plusSeconds(50)))); assertThat(storage.loadPreviousMonthOvertime(YEAR_MONTH)).hasMinutes(5); @@ -77,7 +77,7 @@ void loadPreviousMonthOvertime_truncatesToMinute() @Test void loadOrCreate_createsNewMonthIfNotExists() { - when(fileStorageMock.loadMonthRecord(YEAR_MONTH)).thenReturn(Optional.empty()); + when(fileStorageMock.loadMonth(YEAR_MONTH)).thenReturn(Optional.empty()); final MonthIndex newMonth = storage.loadOrCreate(YEAR_MONTH); @@ -91,7 +91,7 @@ void loadOrCreate_createsNewMonthIfNotExists() void loadOrCreate_loadsExistingMonth() { final JsonMonth month = jsonMonth(YEAR_MONTH, Duration.ofMinutes(4)); - when(fileStorageMock.loadMonthRecord(YEAR_MONTH)).thenReturn(Optional.of(month)); + when(fileStorageMock.loadMonth(YEAR_MONTH)).thenReturn(Optional.of(month)); final MonthIndex newMonth = storage.loadOrCreate(YEAR_MONTH); @@ -111,7 +111,7 @@ void storeMonth() storage.storeMonth(monthIndexMock); - verify(fileStorageMock).writeToFile(eq(YEAR_MONTH), same(month)); + verify(fileStorageMock).store(eq(YEAR_MONTH), same(month)); } @Test diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/DateToFileMapperTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/DateToFileMapperTest.java similarity index 96% rename from logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/DateToFileMapperTest.java rename to logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/DateToFileMapperTest.java index cbf7af96..6d74b948 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/DateToFileMapperTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/DateToFileMapperTest.java @@ -1,4 +1,4 @@ -package org.itsallcode.whiterabbit.logic.storage; +package org.itsallcode.whiterabbit.logic.storage.data; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -11,6 +11,7 @@ import java.time.Month; import java.time.YearMonth; +import org.itsallcode.whiterabbit.logic.storage.data.DateToFileMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; From 70ddd56686f12054bf21cd921e3afd84af3f8207 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 6 Feb 2021 15:45:29 +0100 Subject: [PATCH 03/14] Extract data interfaces for day and month --- .../whiterabbit/jfxui/JavaFxAppUiTest.java | 10 ++--- .../jfxui/JavaFxAppUiTestBase.java | 3 +- .../logic/model/DayActivities.java | 4 +- .../whiterabbit/logic/model/DayRecord.java | 8 ++-- .../whiterabbit/logic/model/MonthIndex.java | 18 ++++---- .../whiterabbit/logic/model/json/DayData.java | 45 +++++++++++++++++++ .../whiterabbit/logic/model/json/JsonDay.java | 18 +++++++- .../logic/model/json/JsonMonth.java | 18 +++++--- .../logic/model/json/MonthData.java | 24 ++++++++++ .../logic/storage/CachingStorage.java | 3 +- .../logic/storage/MonthIndexStorage.java | 13 +++--- .../logic/storage/data/JsonFileStorage.java | 11 +++-- .../logic/storage/data/MonthDataStorage.java | 19 ++++++++ .../logic/model/DayRecordTest.java | 3 +- .../logic/model/MonthIndexTest.java | 17 +++---- .../logic/service/ActivityServiceTest.java | 3 +- .../logic/storage/MonthIndexStorageTest.java | 13 +++--- .../storage/data/DateToFileMapperTest.java | 1 - .../{ => data}/JsonFileStorageTest.java | 38 ++++++++-------- 19 files changed, 197 insertions(+), 72 deletions(-) create mode 100644 logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/DayData.java create mode 100644 logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/MonthData.java create mode 100644 logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/MonthDataStorage.java rename logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/{ => data}/JsonFileStorageTest.java (86%) diff --git a/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTest.java b/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTest.java index 3b84d7a5..afbc2ee5 100644 --- a/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTest.java +++ b/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTest.java @@ -12,8 +12,8 @@ import java.util.Locale; import org.itsallcode.whiterabbit.jfxui.testutil.TestUtil; -import org.itsallcode.whiterabbit.logic.model.json.JsonDay; -import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; +import org.itsallcode.whiterabbit.logic.model.json.DayData; +import org.itsallcode.whiterabbit.logic.model.json.MonthData; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.testfx.api.FxRobot; @@ -97,12 +97,12 @@ void jsonFileWrittenAfterMinuteTick() time().tickMinute(); final LocalTime end = time().getCurrentTimeMinutes(); - final JsonMonth month = loadMonth(today); + final MonthData month = loadMonth(today); assertAll( () -> assertThat(month.getDays()).hasSize(1), - () -> assertThat(month.getDays()).extracting(JsonDay::getBegin).containsExactly(begin), - () -> assertThat(month.getDays()).extracting(JsonDay::getEnd).containsExactly(end)); + () -> assertThat(month.getDays()).extracting(DayData::getBegin).containsExactly(begin), + () -> assertThat(month.getDays()).extracting(DayData::getEnd).containsExactly(end)); } @Test diff --git a/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTestBase.java b/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTestBase.java index 6234203c..bf531fb4 100644 --- a/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTestBase.java +++ b/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTestBase.java @@ -27,6 +27,7 @@ import org.itsallcode.whiterabbit.jfxui.testutil.TimeUtil; import org.itsallcode.whiterabbit.jfxui.testutil.model.ApplicationHelper; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; +import org.itsallcode.whiterabbit.logic.model.json.MonthData; import org.itsallcode.whiterabbit.logic.service.project.ProjectImpl; import org.itsallcode.whiterabbit.logic.service.project.ProjectConfig; import org.junit.jupiter.api.extension.ExtendWith; @@ -181,7 +182,7 @@ protected static ProjectImpl project(final String id, final String label) return project; } - protected JsonMonth loadMonth(final LocalDate date) + protected MonthData loadMonth(final LocalDate date) { final Path file = this.dataDir.resolve(String.valueOf(date.getYear())) .resolve(YearMonth.from(date).toString() + ".json"); diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java index 57905e98..b0903a4b 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java @@ -13,8 +13,8 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.itsallcode.whiterabbit.logic.model.json.DayData; import org.itsallcode.whiterabbit.logic.model.json.JsonActivity; -import org.itsallcode.whiterabbit.logic.model.json.JsonDay; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; public class DayActivities @@ -22,7 +22,7 @@ public class DayActivities private static final Logger LOG = LogManager.getLogger(DayActivities.class); private final ProjectService projectService; - private final JsonDay day; + private final DayData day; final DayRecord dayRecord; DayActivities(DayRecord dayRecord, ProjectService projectService) diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayRecord.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayRecord.java index 29bd7c6d..fa2824b5 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayRecord.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayRecord.java @@ -9,7 +9,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.itsallcode.whiterabbit.api.model.DayType; -import org.itsallcode.whiterabbit.logic.model.json.JsonDay; +import org.itsallcode.whiterabbit.logic.model.json.DayData; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; @@ -19,11 +19,11 @@ public class DayRecord implements RowRecord private final ContractTermsService contractTerms; private final ProjectService projectService; - private final JsonDay day; + private final DayData day; private final MonthIndex month; private final DayRecord previousDay; - public DayRecord(ContractTermsService contractTerms, JsonDay day, DayRecord previousDay, MonthIndex month, + public DayRecord(ContractTermsService contractTerms, DayData day, DayRecord previousDay, MonthIndex month, ProjectService projectService) { this.contractTerms = contractTerms; @@ -148,7 +148,7 @@ public void setInterruption(Duration interruption) day.setInterruption(interruption.isZero() ? null : interruption); } - JsonDay getJsonDay() + DayData getJsonDay() { return day; } diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java index 98b14ea4..3a3a8b0c 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java @@ -15,26 +15,28 @@ import java.util.stream.Stream; import org.itsallcode.whiterabbit.api.model.DayType; +import org.itsallcode.whiterabbit.logic.model.json.DayData; import org.itsallcode.whiterabbit.logic.model.json.JsonDay; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; +import org.itsallcode.whiterabbit.logic.model.json.MonthData; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; public class MonthIndex { - private final JsonMonth record; + private final MonthData record; private final Map days; - private MonthIndex(JsonMonth record, Map days) + private MonthIndex(MonthData record, Map days) { this.record = record; this.days = days; } - public static MonthIndex create(ContractTermsService contractTerms, ProjectService projectService, JsonMonth record) + public static MonthIndex create(ContractTermsService contractTerms, ProjectService projectService, MonthData record) { - final Map jsonDays = record.getDays().stream() - .collect(toMap(JsonDay::getDate, Function.identity())); + final Map jsonDays = record.getDays().stream() + .collect(toMap(DayData::getDate, Function.identity())); final Map days = new HashMap<>(); final MonthIndex monthIndex = new MonthIndex(record, days); @@ -44,7 +46,7 @@ public static MonthIndex create(ContractTermsService contractTerms, ProjectServi for (int day = 1; day <= yearMonth.lengthOfMonth(); day++) { final LocalDate date = yearMonth.atDay(day); - final JsonDay jsonDay = jsonDays.computeIfAbsent(date, d -> createDummyDay(d, contractTerms)); + final DayData jsonDay = jsonDays.computeIfAbsent(date, d -> createDummyDay(d, contractTerms)); final DayRecord dayRecord = new DayRecord(contractTerms, jsonDay, previousDay, monthIndex, projectService); days.put(dayRecord.getDate(), dayRecord); previousDay = dayRecord; @@ -82,7 +84,7 @@ public void put(DayRecord day) public JsonMonth getMonthRecord() { - final List sortedNonDummyJsonDays = getSortedDays() // + final List sortedNonDummyJsonDays = getSortedDays() // .filter(d -> !d.isDummyDay()) // .map(DayRecord::getJsonDay) // .collect(toList()); @@ -126,7 +128,7 @@ public List getVacationDays() { return record.getDays().stream() .filter(day -> day.getType() == DayType.VACATION) - .map(JsonDay::getDate) + .map(DayData::getDate) .collect(toList()); } } diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/DayData.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/DayData.java new file mode 100644 index 00000000..a3e37efd --- /dev/null +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/DayData.java @@ -0,0 +1,45 @@ +package org.itsallcode.whiterabbit.logic.model.json; + +import java.time.Duration; +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.List; + +import org.itsallcode.whiterabbit.api.model.DayType; + +public interface DayData +{ + + LocalDate getDate(); + + DayType getType(); + + LocalTime getBegin(); + + LocalTime getEnd(); + + Duration getInterruption(); + + Duration getWorkingHours(); + + String getComment(); + + void setDate(LocalDate date); + + void setType(DayType type); + + void setBegin(LocalTime begin); + + void setEnd(LocalTime end); + + void setWorkingHours(Duration workingHours); + + void setComment(String comment); + + void setInterruption(Duration interruption); + + List getActivities(); + + void setActivities(List activities); + +} \ No newline at end of file diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonDay.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonDay.java index a1be07af..d11589f6 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonDay.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonDay.java @@ -11,7 +11,7 @@ import org.itsallcode.whiterabbit.api.model.DayType; @JsonbPropertyOrder({ "date", "type", "begin", "end", "interruption", "workingHours", "comment", "activities" }) -public class JsonDay +public class JsonDay implements DayData { @JsonbProperty("date") private LocalDate date; @@ -30,81 +30,97 @@ public class JsonDay @JsonbProperty("activities") private List activities; + @Override public LocalDate getDate() { return date; } + @Override public DayType getType() { return type; } + @Override public LocalTime getBegin() { return begin; } + @Override public LocalTime getEnd() { return end; } + @Override public Duration getInterruption() { return interruption; } + @Override public Duration getWorkingHours() { return workingHours; } + @Override public String getComment() { return comment; } + @Override public void setDate(LocalDate date) { this.date = date; } + @Override public void setType(DayType type) { this.type = type; } + @Override public void setBegin(LocalTime begin) { this.begin = begin; } + @Override public void setEnd(LocalTime end) { this.end = end; } + @Override public void setWorkingHours(Duration workingHours) { this.workingHours = workingHours; } + @Override public void setComment(String comment) { this.comment = comment; } + @Override public void setInterruption(Duration interruption) { this.interruption = interruption; } + @Override public List getActivities() { return activities; } + @Override public void setActivities(List activities) { this.activities = activities; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonMonth.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonMonth.java index 521de128..3fb180b5 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonMonth.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonMonth.java @@ -8,7 +8,7 @@ import javax.json.bind.annotation.JsonbPropertyOrder; @JsonbPropertyOrder({ "year", "month", "overtimePreviousMonth", "days" }) -public class JsonMonth +public class JsonMonth implements MonthData { @JsonbProperty("year") private int year; @@ -17,9 +17,9 @@ public class JsonMonth @JsonbProperty("overtimePreviousMonth") private Duration overtimePreviousMonth; @JsonbProperty("days") - private List days; + private List days; - public static JsonMonth create(JsonMonth record, List sortedDays) + public static JsonMonth create(MonthData record, List sortedDays) { final JsonMonth month = new JsonMonth(); month.setOvertimePreviousMonth(record.getOvertimePreviousMonth()); @@ -29,42 +29,50 @@ public static JsonMonth create(JsonMonth record, List sortedDays) return month; } + @Override public int getYear() { return year; } + @Override public void setYear(int year) { this.year = year; } + @Override public Month getMonth() { return month; } + @Override public void setMonth(Month month) { this.month = month; } + @Override public Duration getOvertimePreviousMonth() { return overtimePreviousMonth; } + @Override public void setOvertimePreviousMonth(Duration overtimePreviousMonth) { this.overtimePreviousMonth = overtimePreviousMonth; } - public List getDays() + @Override + public List getDays() { return days; } - public void setDays(List days) + @Override + public void setDays(List days) { this.days = days; } diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/MonthData.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/MonthData.java new file mode 100644 index 00000000..5e01d76c --- /dev/null +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/MonthData.java @@ -0,0 +1,24 @@ +package org.itsallcode.whiterabbit.logic.model.json; + +import java.time.Duration; +import java.time.Month; +import java.util.List; + +public interface MonthData +{ + int getYear(); + + void setYear(int year); + + Month getMonth(); + + void setMonth(Month month); + + Duration getOvertimePreviousMonth(); + + void setOvertimePreviousMonth(Duration overtimePreviousMonth); + + List getDays(); + + void setDays(List days); +} \ No newline at end of file diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java index 2d4da50e..779958f6 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java @@ -12,13 +12,14 @@ import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; import org.itsallcode.whiterabbit.logic.storage.data.JsonFileStorage; +import org.itsallcode.whiterabbit.logic.storage.data.MonthDataStorage; public interface CachingStorage extends Storage { static CachingStorage create(Path dataDir, ContractTermsService contractTerms, ProjectService projectService) { final Jsonb jsonb = JsonbBuilder.create(new JsonbConfig().withFormatting(true)); - final JsonFileStorage fileStorage = new JsonFileStorage(jsonb, dataDir); + final MonthDataStorage fileStorage = new JsonFileStorage(jsonb, dataDir); final MonthIndexStorage monthIndexStorage = new MonthIndexStorage(contractTerms, projectService, fileStorage); return new CachingStorageImpl(monthIndexStorage); } diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java index 5f46fd8b..e94e82f8 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java @@ -14,9 +14,10 @@ import org.itsallcode.whiterabbit.logic.model.MonthIndex; import org.itsallcode.whiterabbit.logic.model.MultiMonthIndex; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; +import org.itsallcode.whiterabbit.logic.model.json.MonthData; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; -import org.itsallcode.whiterabbit.logic.storage.data.JsonFileStorage; +import org.itsallcode.whiterabbit.logic.storage.data.MonthDataStorage; class MonthIndexStorage implements Storage { @@ -24,10 +25,10 @@ class MonthIndexStorage implements Storage private final ContractTermsService contractTerms; private final ProjectService projectService; - private final JsonFileStorage fileStorage; + private final MonthDataStorage fileStorage; MonthIndexStorage(ContractTermsService contractTerms, ProjectService projectService, - JsonFileStorage fileStorage) + MonthDataStorage fileStorage) { this.contractTerms = contractTerms; this.projectService = projectService; @@ -37,7 +38,7 @@ class MonthIndexStorage implements Storage @Override public Optional loadMonth(YearMonth date) { - return fileStorage.loadMonth(date).map(this::createMonthIndex); + return fileStorage.load(date).map(this::createMonthIndex); } @Override @@ -69,7 +70,7 @@ public List getAvailableDataMonths() private MonthIndex createNewMonth(YearMonth date) { - final JsonMonth month = new JsonMonth(); + final MonthData month = new JsonMonth(); month.setYear(date.getYear()); month.setMonth(date.getMonth()); month.setDays(new ArrayList<>()); @@ -77,7 +78,7 @@ private MonthIndex createNewMonth(YearMonth date) return createMonthIndex(month); } - private MonthIndex createMonthIndex(final JsonMonth jsonMonth) + private MonthIndex createMonthIndex(final MonthData jsonMonth) { return MonthIndex.create(contractTerms, projectService, jsonMonth); } diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java index 2c6cb50e..4c21c283 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java @@ -20,8 +20,9 @@ import org.apache.logging.log4j.Logger; import org.itsallcode.whiterabbit.logic.Config; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; +import org.itsallcode.whiterabbit.logic.model.json.MonthData; -public class JsonFileStorage +public class JsonFileStorage implements MonthDataStorage { private static final Logger LOG = LogManager.getLogger(JsonFileStorage.class); @@ -39,7 +40,8 @@ public JsonFileStorage(Jsonb jsonb, Path dataDir) this.dateToFileMapper = dateToFileMapper; } - public Optional loadMonth(YearMonth date) + @Override + public Optional load(YearMonth date) { final Path file = dateToFileMapper.getPathForDate(date); if (file.toFile().exists()) @@ -70,7 +72,8 @@ private JsonMonth loadFromFile(Path file) } } - public void store(YearMonth yearMonth, JsonMonth record) + @Override + public void store(YearMonth yearMonth, MonthData record) { final Path file = dateToFileMapper.getPathForDate(yearMonth); LOG.trace("Write month {} to file {}", yearMonth, file); @@ -102,11 +105,13 @@ private void createDirectory(Path dir) } } + @Override public List getAvailableDataMonths() { return dateToFileMapper.getAllYearMonths().sorted().collect(toList()); } + @Override public List loadAll() { return dateToFileMapper.getAllFiles() diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/MonthDataStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/MonthDataStorage.java new file mode 100644 index 00000000..00258653 --- /dev/null +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/MonthDataStorage.java @@ -0,0 +1,19 @@ +package org.itsallcode.whiterabbit.logic.storage.data; + +import java.time.YearMonth; +import java.util.List; +import java.util.Optional; + +import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; +import org.itsallcode.whiterabbit.logic.model.json.MonthData; + +public interface MonthDataStorage +{ + Optional load(YearMonth date); + + void store(YearMonth yearMonth, MonthData record); + + List getAvailableDataMonths(); + + List loadAll(); +} \ No newline at end of file diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java index c25c461b..27b580d8 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java @@ -12,6 +12,7 @@ import org.itsallcode.whiterabbit.logic.Config; import org.itsallcode.whiterabbit.logic.model.json.JsonDay; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; +import org.itsallcode.whiterabbit.logic.model.json.MonthData; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; import org.itsallcode.whiterabbit.logic.test.TestingConfig; @@ -428,7 +429,7 @@ void getCustomWorkingTimeReturnsRealValue() private MonthIndex month(LocalDate date, Duration overtimePreviousMonth, JsonDay... days) { - final JsonMonth jsonMonth = new JsonMonth(); + final MonthData jsonMonth = new JsonMonth(); jsonMonth.setDays(asList(days)); jsonMonth.setMonth(date.getMonth()); jsonMonth.setYear(date.getYear()); diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java index 4d381679..410e2357 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java @@ -13,6 +13,7 @@ import org.itsallcode.whiterabbit.logic.Config; import org.itsallcode.whiterabbit.logic.model.json.JsonDay; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; +import org.itsallcode.whiterabbit.logic.model.json.MonthData; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; import org.itsallcode.whiterabbit.logic.test.TestingConfig; @@ -76,7 +77,7 @@ void testCalculateTotalOvertimeMultipleDaysNegativeOvertime() @Test void testSetOvertimePreviousMonthUpdatesJsonRecord() { - final JsonMonth jsonMonth = jsonMonth(Duration.ofHours(1)); + final MonthData jsonMonth = jsonMonth(Duration.ofHours(1)); final MonthIndex monthIndex = create(jsonMonth); monthIndex.setOvertimePreviousMonth(Duration.ofHours(2)); @@ -86,7 +87,7 @@ void testSetOvertimePreviousMonthUpdatesJsonRecord() @Test void testSetOvertimePreviousMonthUpdatesTotalOvertime() { - final JsonMonth jsonMonth = jsonMonth(Duration.ofHours(1)); + final MonthData jsonMonth = jsonMonth(Duration.ofHours(1)); final MonthIndex monthIndex = create(jsonMonth); assertThat(monthIndex.getTotalOvertime()).isEqualTo(Duration.ofHours(1)); @@ -127,7 +128,7 @@ void gettingNewDayReturnsEmptyDay() void gettingDaysDoesNotAddThemToJson() { final LocalDate date = LocalDate.of(2020, 5, 4); - final JsonMonth jsonMonth = jsonMonth(YearMonth.from(date), null); + final MonthData jsonMonth = jsonMonth(YearMonth.from(date), null); final MonthIndex monthIndex = create(TestingConfig.builder().build(), jsonMonth); final DayRecord day = monthIndex.getDay(date); @@ -172,14 +173,14 @@ private Duration calculateTotalOvertime(Duration overtimePreviousMonth, JsonDay. return create(jsonMonth(overtimePreviousMonth, days)).getTotalOvertime(); } - private JsonMonth jsonMonth(Duration overtimePreviousMonth, JsonDay... days) + private MonthData jsonMonth(Duration overtimePreviousMonth, JsonDay... days) { return jsonMonth(YearMonth.of(2019, Month.MAY), overtimePreviousMonth, days); } - private JsonMonth jsonMonth(YearMonth yearMonth, Duration overtimePreviousMonth, JsonDay... days) + private MonthData jsonMonth(YearMonth yearMonth, Duration overtimePreviousMonth, JsonDay... days) { - final JsonMonth month = new JsonMonth(); + final MonthData month = new JsonMonth(); month.setYear(yearMonth.getYear()); month.setMonth(yearMonth.getMonth()); month.setDays(asList(days)); @@ -200,12 +201,12 @@ private JsonDay day(Duration overtime, int dayOfMonth) return day; } - private MonthIndex create(JsonMonth record) + private MonthIndex create(MonthData record) { return create(TestingConfig.builder().build(), record); } - private MonthIndex create(Config config, JsonMonth record) + private MonthIndex create(Config config, MonthData record) { return MonthIndex.create(new ContractTermsService(config), projectServiceMock, record); } diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ActivityServiceTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ActivityServiceTest.java index e96a5984..1daa7180 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ActivityServiceTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ActivityServiceTest.java @@ -17,6 +17,7 @@ import org.itsallcode.whiterabbit.logic.autocomplete.AutocompleteService; import org.itsallcode.whiterabbit.logic.model.MonthIndex; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; +import org.itsallcode.whiterabbit.logic.model.json.MonthData; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectImpl; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; @@ -126,7 +127,7 @@ void removeActivity() private MonthIndex createMonth() { - final JsonMonth monthRecord = new JsonMonth(); + final MonthData monthRecord = new JsonMonth(); monthRecord.setDays(new ArrayList<>()); monthRecord.setYear(DATE.getYear()); monthRecord.setMonth(DATE.getMonth()); diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java index f15e31eb..7b6aefbe 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java @@ -19,6 +19,7 @@ import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; +import org.itsallcode.whiterabbit.logic.storage.data.MonthDataStorage; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -36,7 +37,7 @@ class MonthIndexStorageTest @Mock ProjectService projectServiceMock; @Mock - JsonFileStorage fileStorageMock; + MonthDataStorage fileStorageMock; @Mock MonthIndex monthIndexMock; @@ -51,7 +52,7 @@ void setUp() @Test void loadPreviousMonthOvertime_returnsZero_whenNoPreviousMonth() { - when(fileStorageMock.loadMonth(YearMonth.of(2020, Month.OCTOBER))).thenReturn(Optional.empty()); + when(fileStorageMock.load(YearMonth.of(2020, Month.OCTOBER))).thenReturn(Optional.empty()); assertThat(storage.loadPreviousMonthOvertime(YEAR_MONTH)).isZero(); } @@ -59,7 +60,7 @@ void loadPreviousMonthOvertime_returnsZero_whenNoPreviousMonth() @Test void loadPreviousMonthOvertime_returnsPreviousMonthOvertime() { - when(fileStorageMock.loadMonth(PREVIOUS_MONTH)) + when(fileStorageMock.load(PREVIOUS_MONTH)) .thenReturn(Optional.of(jsonMonth(PREVIOUS_MONTH, Duration.ofMinutes(5)))); assertThat(storage.loadPreviousMonthOvertime(YEAR_MONTH)).hasMinutes(5); @@ -68,7 +69,7 @@ void loadPreviousMonthOvertime_returnsPreviousMonthOvertime() @Test void loadPreviousMonthOvertime_truncatesToMinute() { - when(fileStorageMock.loadMonth(PREVIOUS_MONTH)) + when(fileStorageMock.load(PREVIOUS_MONTH)) .thenReturn(Optional.of(jsonMonth(PREVIOUS_MONTH, Duration.ofMinutes(5).plusSeconds(50)))); assertThat(storage.loadPreviousMonthOvertime(YEAR_MONTH)).hasMinutes(5); @@ -77,7 +78,7 @@ void loadPreviousMonthOvertime_truncatesToMinute() @Test void loadOrCreate_createsNewMonthIfNotExists() { - when(fileStorageMock.loadMonth(YEAR_MONTH)).thenReturn(Optional.empty()); + when(fileStorageMock.load(YEAR_MONTH)).thenReturn(Optional.empty()); final MonthIndex newMonth = storage.loadOrCreate(YEAR_MONTH); @@ -91,7 +92,7 @@ void loadOrCreate_createsNewMonthIfNotExists() void loadOrCreate_loadsExistingMonth() { final JsonMonth month = jsonMonth(YEAR_MONTH, Duration.ofMinutes(4)); - when(fileStorageMock.loadMonth(YEAR_MONTH)).thenReturn(Optional.of(month)); + when(fileStorageMock.load(YEAR_MONTH)).thenReturn(Optional.of(month)); final MonthIndex newMonth = storage.loadOrCreate(YEAR_MONTH); diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/DateToFileMapperTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/DateToFileMapperTest.java index 6d74b948..8d303f72 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/DateToFileMapperTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/DateToFileMapperTest.java @@ -11,7 +11,6 @@ import java.time.Month; import java.time.YearMonth; -import org.itsallcode.whiterabbit.logic.storage.data.DateToFileMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/JsonFileStorageTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorageTest.java similarity index 86% rename from logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/JsonFileStorageTest.java rename to logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorageTest.java index cfcade75..af2c976f 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/JsonFileStorageTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorageTest.java @@ -1,4 +1,4 @@ -package org.itsallcode.whiterabbit.logic.storage; +package org.itsallcode.whiterabbit.logic.storage.data; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -20,7 +20,7 @@ import javax.json.bind.JsonbConfig; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; -import org.itsallcode.whiterabbit.logic.storage.data.DateToFileMapper; +import org.itsallcode.whiterabbit.logic.model.json.MonthData; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -69,19 +69,19 @@ void loadMonthReturnsEmptyOptional_WhenLegacyFileDoesNotExist() { when(dateToFileMapperMock.getPathForDate(YEAR_MONTH)).thenReturn(tempDir.resolve("does-not-exist")); when(dateToFileMapperMock.getLegacyPathForDate(YEAR_MONTH)).thenReturn(tempDir.resolve("does-not-exist")); - assertThat(jsonFileStorage.loadMonth(YEAR_MONTH)).isEmpty(); + assertThat(jsonFileStorage.load(YEAR_MONTH)).isEmpty(); } @Test void loadMonthReturnsMonth_WhenLegacyFileExists() throws IOException { - final JsonMonth month = new JsonMonth(); + final MonthData month = new JsonMonth(); month.setYear(2020); final Path file = writeTempFile(month); when(dateToFileMapperMock.getPathForDate(YEAR_MONTH)).thenReturn(tempDir.resolve("does-not-exist")); when(dateToFileMapperMock.getLegacyPathForDate(YEAR_MONTH)).thenReturn(file); - final Optional loadedMonth = jsonFileStorage.loadMonth(YEAR_MONTH); + final Optional loadedMonth = jsonFileStorage.load(YEAR_MONTH); assertThat(loadedMonth).isNotEmpty(); assertThat(loadedMonth.get().getYear()).isEqualTo(2020); } @@ -89,12 +89,12 @@ void loadMonthReturnsMonth_WhenLegacyFileExists() throws IOException @Test void loadMonthReturnsMonth_WhenFileExists() throws IOException { - final JsonMonth month = new JsonMonth(); + final MonthData month = new JsonMonth(); month.setYear(2020); final Path file = writeTempFile(month); when(dateToFileMapperMock.getPathForDate(YEAR_MONTH)).thenReturn(file); - final Optional loadedMonth = jsonFileStorage.loadMonth(YEAR_MONTH); + final Optional loadedMonth = jsonFileStorage.load(YEAR_MONTH); assertThat(loadedMonth).isNotEmpty(); assertThat(loadedMonth.get().getYear()).isEqualTo(2020); } @@ -105,7 +105,7 @@ void writeToFile_writesFile() throws IOException final Path file = createTempFile(); when(dateToFileMapperMock.getPathForDate(YEAR_MONTH)).thenReturn(file); - final JsonMonth month = new JsonMonth(); + final MonthData month = new JsonMonth(); month.setYear(2020); jsonFileStorage.store(YEAR_MONTH, month); @@ -118,7 +118,7 @@ void writeToFile_createsDirectory() throws IOException final Path file = tempDir.resolve("sub-dir1").resolve("sub-dir2").resolve("file.json"); when(dateToFileMapperMock.getPathForDate(YEAR_MONTH)).thenReturn(file); - final JsonMonth month = new JsonMonth(); + final MonthData month = new JsonMonth(); month.setYear(2020); jsonFileStorage.store(YEAR_MONTH, month); @@ -149,8 +149,8 @@ void loadAll_returnsFiles() throws IOException final Path file2 = tempDir.resolve("file2.json"); when(dateToFileMapperMock.getAllFiles()).thenReturn(Stream.of(file1, file2)); - final JsonMonth month1 = month(2019, Month.DECEMBER); - final JsonMonth month2 = month(2020, Month.JANUARY); + final MonthData month1 = month(2019, Month.DECEMBER); + final MonthData month2 = month(2020, Month.JANUARY); writeMonth(month1, file1); writeMonth(month2, file2); @@ -169,9 +169,9 @@ void loadAll_sortsByYearMonth() throws IOException final Path file3 = tempDir.resolve("file3.json"); when(dateToFileMapperMock.getAllFiles()).thenReturn(Stream.of(file3, file2, file1)); - final JsonMonth month1 = month(2019, Month.DECEMBER); - final JsonMonth month2 = month(2020, Month.JANUARY); - final JsonMonth month3 = month(2020, Month.APRIL); + final MonthData month1 = month(2019, Month.DECEMBER); + final MonthData month2 = month(2020, Month.JANUARY); + final MonthData month3 = month(2020, Month.APRIL); writeMonth(month1, file1); writeMonth(month2, file2); writeMonth(month3, file3); @@ -184,28 +184,28 @@ void loadAll_sortsByYearMonth() throws IOException assertMonth(months.get(2), month3); } - private void assertMonth(JsonMonth actual, JsonMonth expected) + private void assertMonth(MonthData actual, MonthData expected) { assertAll(() -> assertThat(actual.getYear()).isEqualTo(expected.getYear()), () -> assertThat(actual.getMonth()).isEqualTo(expected.getMonth())); } - private JsonMonth month(int year, Month month) + private MonthData month(int year, Month month) { - final JsonMonth jsonMonth = new JsonMonth(); + final MonthData jsonMonth = new JsonMonth(); jsonMonth.setYear(year); jsonMonth.setMonth(month); return jsonMonth; } - private Path writeTempFile(JsonMonth month) throws IOException + private Path writeTempFile(MonthData month) throws IOException { final Path file = createTempFile(); writeMonth(month, file); return file; } - private void writeMonth(JsonMonth month, final Path file) throws IOException + private void writeMonth(MonthData month, final Path file) throws IOException { Files.writeString(file, jsonb.toJson(month)); } From ddc2f6dcea9bed5bf62a998a6ec1788caa7063a2 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 6 Feb 2021 15:54:18 +0100 Subject: [PATCH 04/14] Fix compileOnly dependencies in Eclipse --- plugins/build.gradle | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/build.gradle b/plugins/build.gradle index d343eb8e..df89f59d 100644 --- a/plugins/build.gradle +++ b/plugins/build.gradle @@ -11,6 +11,12 @@ subprojects { archiveClassifier.set(null) archiveVersion.set("") } + + eclipse { + classpath { + plusConfigurations += [ configurations.compileOnly ] + } + } } def pluginBuildTasks = project.subprojects.collect {it.tasks['shadowJar']} From c4a33de67895069dc89df2aaf4f3bcaf8c06e7b9 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 6 Feb 2021 15:58:11 +0100 Subject: [PATCH 05/14] Extract interface for activity --- .../whiterabbit/logic/model/Activity.java | 6 +++--- .../logic/model/DayActivities.java | 19 +++++++++--------- .../logic/model/json/ActivityData.java | 20 +++++++++++++++++++ .../whiterabbit/logic/model/json/DayData.java | 6 ++---- .../logic/model/json/JsonActivity.java | 9 ++++++++- .../whiterabbit/logic/model/json/JsonDay.java | 6 +++--- .../logic/model/DayActivitiesTest.java | 7 ++++--- 7 files changed, 50 insertions(+), 23 deletions(-) create mode 100644 logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/ActivityData.java diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/Activity.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/Activity.java index b25fd4b4..371b1089 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/Activity.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/Activity.java @@ -4,18 +4,18 @@ import java.util.Objects; import org.itsallcode.whiterabbit.api.model.Project; -import org.itsallcode.whiterabbit.logic.model.json.JsonActivity; +import org.itsallcode.whiterabbit.logic.model.json.ActivityData; import org.itsallcode.whiterabbit.logic.service.project.ProjectImpl; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; public class Activity implements RowRecord { - final JsonActivity jsonActivity; + final ActivityData jsonActivity; private final DayActivities day; private final int index; private final ProjectService projectService; - public Activity(int index, JsonActivity jsonActivity, DayActivities day, ProjectService projectService) + public Activity(int index, ActivityData jsonActivity, DayActivities day, ProjectService projectService) { this.index = index; this.jsonActivity = jsonActivity; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java index b0903a4b..6878c094 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java @@ -13,6 +13,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.itsallcode.whiterabbit.logic.model.json.ActivityData; import org.itsallcode.whiterabbit.logic.model.json.DayData; import org.itsallcode.whiterabbit.logic.model.json.JsonActivity; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; @@ -53,7 +54,7 @@ public Activity add() public List getAll() { - final List jsonActivities = getActivities().collect(toList()); + final List jsonActivities = getActivities().collect(toList()); return IntStream.range(0, jsonActivities.size()) .mapToObj(i -> wrapActivity(jsonActivities.get(i), i)) .collect(toList()); @@ -65,14 +66,14 @@ public boolean isEmpty() .findFirst().orElse(true); } - private Stream getActivities() + private Stream getActivities() { return Optional.ofNullable(day.getActivities()) .orElse(emptyList()) .stream(); } - private Activity wrapActivity(JsonActivity activity, int index) + private Activity wrapActivity(ActivityData activity, int index) { return new Activity(index, activity, this, projectService); } @@ -98,7 +99,7 @@ public void remove(int index) } } - public void setRemainderActivity(JsonActivity activity, boolean remainder) + public void setRemainderActivity(ActivityData activity, boolean remainder) { if (activity.isRemainder() == remainder) { @@ -113,9 +114,9 @@ public void setRemainderActivity(JsonActivity activity, boolean remainder) return; } - final List currentRemainders = getRemainderActivities(); + final List currentRemainders = getRemainderActivities(); LOG.debug("Found {} remainder activities: deactivate them", currentRemainders.size()); - for (final JsonActivity remainderActivity : currentRemainders) + for (final ActivityData remainderActivity : currentRemainders) { final Duration unallocatedDuration = getUnallocatedDuration(); remainderActivity.setDuration(unallocatedDuration); @@ -127,7 +128,7 @@ public void setRemainderActivity(JsonActivity activity, boolean remainder) private Duration getUnallocatedDuration() { - final Duration allocatedDuration = getActivities().map(JsonActivity::getDuration) + final Duration allocatedDuration = getActivities().map(ActivityData::getDuration) .filter(Objects::nonNull) .reduce((d1, d2) -> d1.plus(d2)) .orElse(Duration.ZERO); @@ -136,7 +137,7 @@ private Duration getUnallocatedDuration() public boolean isValidAllocation() { - final List remainderActivities = getActivities() + final List remainderActivities = getActivities() .filter(a -> a.getDuration() == null) .collect(toList()); if (remainderActivities.size() > 1) @@ -159,7 +160,7 @@ public boolean isValidAllocation() return true; } - private List getRemainderActivities() + private List getRemainderActivities() { return getActivities().filter(a -> a.getDuration() == null).collect(toList()); } diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/ActivityData.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/ActivityData.java new file mode 100644 index 00000000..588de727 --- /dev/null +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/ActivityData.java @@ -0,0 +1,20 @@ +package org.itsallcode.whiterabbit.logic.model.json; + +import java.time.Duration; + +public interface ActivityData +{ + String getProjectId(); + + void setProjectId(String id); + + Duration getDuration(); + + boolean isRemainder(); + + void setDuration(Duration duration); + + String getComment(); + + void setComment(String comment); +} \ No newline at end of file diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/DayData.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/DayData.java index a3e37efd..dca3fe41 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/DayData.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/DayData.java @@ -9,7 +9,6 @@ public interface DayData { - LocalDate getDate(); DayType getType(); @@ -38,8 +37,7 @@ public interface DayData void setInterruption(Duration interruption); - List getActivities(); - - void setActivities(List activities); + List getActivities(); + void setActivities(List activities); } \ No newline at end of file diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonActivity.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonActivity.java index 7ed8f794..d3f33eff 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonActivity.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonActivity.java @@ -8,7 +8,7 @@ @JsonbPropertyOrder({ "projectId", "duration", "comment" }) @JsonbVisibility(FieldAccessStrategy.class) -public class JsonActivity +public class JsonActivity implements ActivityData { @JsonbProperty("projectId") private String projectId; @@ -24,36 +24,43 @@ public JsonActivity() this.comment = null; } + @Override public String getProjectId() { return projectId; } + @Override public void setProjectId(String id) { this.projectId = id; } + @Override public Duration getDuration() { return duration; } + @Override public boolean isRemainder() { return getDuration() == null; } + @Override public void setDuration(Duration duration) { this.duration = duration; } + @Override public String getComment() { return comment; } + @Override public void setComment(String comment) { this.comment = comment; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonDay.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonDay.java index d11589f6..da8536e5 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonDay.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonDay.java @@ -28,7 +28,7 @@ public class JsonDay implements DayData @JsonbProperty("comment") private String comment; @JsonbProperty("activities") - private List activities; + private List activities; @Override public LocalDate getDate() @@ -115,13 +115,13 @@ public void setInterruption(Duration interruption) } @Override - public List getActivities() + public List getActivities() { return activities; } @Override - public void setActivities(List activities) + public void setActivities(List activities) { this.activities = activities; } diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayActivitiesTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayActivitiesTest.java index 298ceb6e..9024bbe5 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayActivitiesTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayActivitiesTest.java @@ -8,6 +8,7 @@ import java.time.Duration; import java.util.ArrayList; +import org.itsallcode.whiterabbit.logic.model.json.ActivityData; import org.itsallcode.whiterabbit.logic.model.json.JsonActivity; import org.itsallcode.whiterabbit.logic.model.json.JsonDay; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; @@ -282,7 +283,7 @@ void setRemainderToFalse() when(contractTermsMock.getWorkingTime(same(dayRecord))).thenReturn(Duration.ofHours(7)); - final JsonActivity activity = new JsonActivity(); + final ActivityData activity = new JsonActivity(); activity.setDuration(null); activities.setRemainderActivity(activity, false); @@ -299,7 +300,7 @@ void setRemainderToFalseSetsRemainingDuration() when(contractTermsMock.getWorkingTime(same(dayRecord))).thenReturn(Duration.ofHours(7)); activities.add().setDuration(Duration.ofHours(3)); - final JsonActivity activity = new JsonActivity(); + final ActivityData activity = new JsonActivity(); activity.setDuration(null); activities.setRemainderActivity(activity, false); @@ -317,7 +318,7 @@ void setRemainderToFalseSetsRemainingDurationMultipleActivities() activities.add().setDuration(Duration.ofHours(3)); activities.add().setDuration(Duration.ofMinutes(30)); - final JsonActivity activity = new JsonActivity(); + final ActivityData activity = new JsonActivity(); activity.setDuration(null); activities.setRemainderActivity(activity, false); From ff896a473f5ffe7a1bdd0d0bfcfc2ef080795383 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 6 Feb 2021 16:00:44 +0100 Subject: [PATCH 06/14] Move MonthDataStorage to api project --- .../whiterabbit/api/MonthDataStorage.java | 18 ++++++++++++++++++ .../whiterabbit/api/model}/ActivityData.java | 2 +- .../whiterabbit/api/model}/DayData.java | 4 +--- .../whiterabbit/api/model}/MonthData.java | 2 +- .../whiterabbit/jfxui/JavaFxAppUiTest.java | 4 ++-- .../jfxui/JavaFxAppUiTestBase.java | 2 +- .../whiterabbit/logic/model/Activity.java | 2 +- .../logic/model/DayActivities.java | 4 ++-- .../whiterabbit/logic/model/DayRecord.java | 2 +- .../whiterabbit/logic/model/MonthIndex.java | 4 ++-- .../logic/model/json/JsonActivity.java | 2 ++ .../whiterabbit/logic/model/json/JsonDay.java | 2 ++ .../logic/model/json/JsonMonth.java | 3 +++ .../logic/storage/CachingStorage.java | 2 +- .../logic/storage/MonthIndexStorage.java | 4 ++-- .../logic/storage/data/JsonFileStorage.java | 7 ++++--- .../logic/storage/data/MonthDataStorage.java | 19 ------------------- .../logic/model/DayActivitiesTest.java | 2 +- .../logic/model/DayRecordTest.java | 2 +- .../logic/model/MonthIndexTest.java | 2 +- .../logic/service/ActivityServiceTest.java | 2 +- .../logic/storage/MonthIndexStorageTest.java | 2 +- .../storage/data/JsonFileStorageTest.java | 10 +++++----- 23 files changed, 54 insertions(+), 49 deletions(-) create mode 100644 api/src/main/java/org/itsallcode/whiterabbit/api/MonthDataStorage.java rename {logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json => api/src/main/java/org/itsallcode/whiterabbit/api/model}/ActivityData.java (84%) rename {logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json => api/src/main/java/org/itsallcode/whiterabbit/api/model}/DayData.java (86%) rename {logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json => api/src/main/java/org/itsallcode/whiterabbit/api/model}/MonthData.java (88%) delete mode 100644 logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/MonthDataStorage.java diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/MonthDataStorage.java b/api/src/main/java/org/itsallcode/whiterabbit/api/MonthDataStorage.java new file mode 100644 index 00000000..57b1237f --- /dev/null +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/MonthDataStorage.java @@ -0,0 +1,18 @@ +package org.itsallcode.whiterabbit.api; + +import java.time.YearMonth; +import java.util.List; +import java.util.Optional; + +import org.itsallcode.whiterabbit.api.model.MonthData; + +public interface MonthDataStorage +{ + Optional load(YearMonth date); + + void store(YearMonth yearMonth, MonthData record); + + List getAvailableDataMonths(); + + List loadAll(); +} \ No newline at end of file diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/ActivityData.java b/api/src/main/java/org/itsallcode/whiterabbit/api/model/ActivityData.java similarity index 84% rename from logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/ActivityData.java rename to api/src/main/java/org/itsallcode/whiterabbit/api/model/ActivityData.java index 588de727..6d107153 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/ActivityData.java +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/model/ActivityData.java @@ -1,4 +1,4 @@ -package org.itsallcode.whiterabbit.logic.model.json; +package org.itsallcode.whiterabbit.api.model; import java.time.Duration; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/DayData.java b/api/src/main/java/org/itsallcode/whiterabbit/api/model/DayData.java similarity index 86% rename from logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/DayData.java rename to api/src/main/java/org/itsallcode/whiterabbit/api/model/DayData.java index dca3fe41..588615cb 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/DayData.java +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/model/DayData.java @@ -1,12 +1,10 @@ -package org.itsallcode.whiterabbit.logic.model.json; +package org.itsallcode.whiterabbit.api.model; import java.time.Duration; import java.time.LocalDate; import java.time.LocalTime; import java.util.List; -import org.itsallcode.whiterabbit.api.model.DayType; - public interface DayData { LocalDate getDate(); diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/MonthData.java b/api/src/main/java/org/itsallcode/whiterabbit/api/model/MonthData.java similarity index 88% rename from logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/MonthData.java rename to api/src/main/java/org/itsallcode/whiterabbit/api/model/MonthData.java index 5e01d76c..46a4b90b 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/MonthData.java +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/model/MonthData.java @@ -1,4 +1,4 @@ -package org.itsallcode.whiterabbit.logic.model.json; +package org.itsallcode.whiterabbit.api.model; import java.time.Duration; import java.time.Month; diff --git a/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTest.java b/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTest.java index afbc2ee5..f40f1270 100644 --- a/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTest.java +++ b/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTest.java @@ -11,9 +11,9 @@ import java.time.YearMonth; import java.util.Locale; +import org.itsallcode.whiterabbit.api.model.DayData; +import org.itsallcode.whiterabbit.api.model.MonthData; import org.itsallcode.whiterabbit.jfxui.testutil.TestUtil; -import org.itsallcode.whiterabbit.logic.model.json.DayData; -import org.itsallcode.whiterabbit.logic.model.json.MonthData; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.testfx.api.FxRobot; diff --git a/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTestBase.java b/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTestBase.java index bf531fb4..df05eed3 100644 --- a/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTestBase.java +++ b/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTestBase.java @@ -23,11 +23,11 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.itsallcode.whiterabbit.api.model.MonthData; import org.itsallcode.whiterabbit.jfxui.testutil.TableRowExpectedContent; import org.itsallcode.whiterabbit.jfxui.testutil.TimeUtil; import org.itsallcode.whiterabbit.jfxui.testutil.model.ApplicationHelper; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; -import org.itsallcode.whiterabbit.logic.model.json.MonthData; import org.itsallcode.whiterabbit.logic.service.project.ProjectImpl; import org.itsallcode.whiterabbit.logic.service.project.ProjectConfig; import org.junit.jupiter.api.extension.ExtendWith; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/Activity.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/Activity.java index 371b1089..93b7620e 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/Activity.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/Activity.java @@ -3,8 +3,8 @@ import java.time.Duration; import java.util.Objects; +import org.itsallcode.whiterabbit.api.model.ActivityData; import org.itsallcode.whiterabbit.api.model.Project; -import org.itsallcode.whiterabbit.logic.model.json.ActivityData; import org.itsallcode.whiterabbit.logic.service.project.ProjectImpl; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java index 6878c094..44bd4f7c 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java @@ -13,8 +13,8 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.itsallcode.whiterabbit.logic.model.json.ActivityData; -import org.itsallcode.whiterabbit.logic.model.json.DayData; +import org.itsallcode.whiterabbit.api.model.ActivityData; +import org.itsallcode.whiterabbit.api.model.DayData; import org.itsallcode.whiterabbit.logic.model.json.JsonActivity; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayRecord.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayRecord.java index fa2824b5..ef1e649b 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayRecord.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayRecord.java @@ -8,8 +8,8 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.itsallcode.whiterabbit.api.model.DayData; import org.itsallcode.whiterabbit.api.model.DayType; -import org.itsallcode.whiterabbit.logic.model.json.DayData; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java index 3a3a8b0c..b8d35af3 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java @@ -14,11 +14,11 @@ import java.util.function.Function; import java.util.stream.Stream; +import org.itsallcode.whiterabbit.api.model.DayData; import org.itsallcode.whiterabbit.api.model.DayType; -import org.itsallcode.whiterabbit.logic.model.json.DayData; +import org.itsallcode.whiterabbit.api.model.MonthData; import org.itsallcode.whiterabbit.logic.model.json.JsonDay; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; -import org.itsallcode.whiterabbit.logic.model.json.MonthData; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonActivity.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonActivity.java index d3f33eff..db8a1fdd 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonActivity.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonActivity.java @@ -6,6 +6,8 @@ import javax.json.bind.annotation.JsonbPropertyOrder; import javax.json.bind.annotation.JsonbVisibility; +import org.itsallcode.whiterabbit.api.model.ActivityData; + @JsonbPropertyOrder({ "projectId", "duration", "comment" }) @JsonbVisibility(FieldAccessStrategy.class) public class JsonActivity implements ActivityData diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonDay.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonDay.java index da8536e5..f89a36e7 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonDay.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonDay.java @@ -8,6 +8,8 @@ import javax.json.bind.annotation.JsonbProperty; import javax.json.bind.annotation.JsonbPropertyOrder; +import org.itsallcode.whiterabbit.api.model.ActivityData; +import org.itsallcode.whiterabbit.api.model.DayData; import org.itsallcode.whiterabbit.api.model.DayType; @JsonbPropertyOrder({ "date", "type", "begin", "end", "interruption", "workingHours", "comment", "activities" }) diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonMonth.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonMonth.java index 3fb180b5..f0f81d02 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonMonth.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonMonth.java @@ -7,6 +7,9 @@ import javax.json.bind.annotation.JsonbProperty; import javax.json.bind.annotation.JsonbPropertyOrder; +import org.itsallcode.whiterabbit.api.model.DayData; +import org.itsallcode.whiterabbit.api.model.MonthData; + @JsonbPropertyOrder({ "year", "month", "overtimePreviousMonth", "days" }) public class JsonMonth implements MonthData { diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java index 779958f6..3d64db28 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java @@ -8,11 +8,11 @@ import javax.json.bind.JsonbBuilder; import javax.json.bind.JsonbConfig; +import org.itsallcode.whiterabbit.api.MonthDataStorage; import org.itsallcode.whiterabbit.logic.model.DayRecord; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; import org.itsallcode.whiterabbit.logic.storage.data.JsonFileStorage; -import org.itsallcode.whiterabbit.logic.storage.data.MonthDataStorage; public interface CachingStorage extends Storage { diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java index e94e82f8..ea04e322 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java @@ -11,13 +11,13 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.itsallcode.whiterabbit.api.MonthDataStorage; +import org.itsallcode.whiterabbit.api.model.MonthData; import org.itsallcode.whiterabbit.logic.model.MonthIndex; import org.itsallcode.whiterabbit.logic.model.MultiMonthIndex; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; -import org.itsallcode.whiterabbit.logic.model.json.MonthData; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; -import org.itsallcode.whiterabbit.logic.storage.data.MonthDataStorage; class MonthIndexStorage implements Storage { diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java index 4c21c283..2c1e88b2 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java @@ -18,9 +18,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.itsallcode.whiterabbit.api.MonthDataStorage; +import org.itsallcode.whiterabbit.api.model.MonthData; import org.itsallcode.whiterabbit.logic.Config; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; -import org.itsallcode.whiterabbit.logic.model.json.MonthData; public class JsonFileStorage implements MonthDataStorage { @@ -41,7 +42,7 @@ public JsonFileStorage(Jsonb jsonb, Path dataDir) } @Override - public Optional load(YearMonth date) + public Optional load(YearMonth date) { final Path file = dateToFileMapper.getPathForDate(date); if (file.toFile().exists()) @@ -112,7 +113,7 @@ public List getAvailableDataMonths() } @Override - public List loadAll() + public List loadAll() { return dateToFileMapper.getAllFiles() .filter(file -> !file.getFileName().toString().equals(Config.PROJECTS_JSON)) diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/MonthDataStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/MonthDataStorage.java deleted file mode 100644 index 00258653..00000000 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/MonthDataStorage.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.itsallcode.whiterabbit.logic.storage.data; - -import java.time.YearMonth; -import java.util.List; -import java.util.Optional; - -import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; -import org.itsallcode.whiterabbit.logic.model.json.MonthData; - -public interface MonthDataStorage -{ - Optional load(YearMonth date); - - void store(YearMonth yearMonth, MonthData record); - - List getAvailableDataMonths(); - - List loadAll(); -} \ No newline at end of file diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayActivitiesTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayActivitiesTest.java index 9024bbe5..06d660bb 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayActivitiesTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayActivitiesTest.java @@ -8,7 +8,7 @@ import java.time.Duration; import java.util.ArrayList; -import org.itsallcode.whiterabbit.logic.model.json.ActivityData; +import org.itsallcode.whiterabbit.api.model.ActivityData; import org.itsallcode.whiterabbit.logic.model.json.JsonActivity; import org.itsallcode.whiterabbit.logic.model.json.JsonDay; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java index 27b580d8..91e296b5 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java @@ -9,10 +9,10 @@ import java.time.LocalTime; import org.itsallcode.whiterabbit.api.model.DayType; +import org.itsallcode.whiterabbit.api.model.MonthData; import org.itsallcode.whiterabbit.logic.Config; import org.itsallcode.whiterabbit.logic.model.json.JsonDay; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; -import org.itsallcode.whiterabbit.logic.model.json.MonthData; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; import org.itsallcode.whiterabbit.logic.test.TestingConfig; diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java index 410e2357..a32a702e 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java @@ -10,10 +10,10 @@ import java.time.YearMonth; import org.itsallcode.whiterabbit.api.model.DayType; +import org.itsallcode.whiterabbit.api.model.MonthData; import org.itsallcode.whiterabbit.logic.Config; import org.itsallcode.whiterabbit.logic.model.json.JsonDay; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; -import org.itsallcode.whiterabbit.logic.model.json.MonthData; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; import org.itsallcode.whiterabbit.logic.test.TestingConfig; diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ActivityServiceTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ActivityServiceTest.java index 1daa7180..9199eb27 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ActivityServiceTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ActivityServiceTest.java @@ -14,10 +14,10 @@ import java.util.NoSuchElementException; import java.util.Optional; +import org.itsallcode.whiterabbit.api.model.MonthData; import org.itsallcode.whiterabbit.logic.autocomplete.AutocompleteService; import org.itsallcode.whiterabbit.logic.model.MonthIndex; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; -import org.itsallcode.whiterabbit.logic.model.json.MonthData; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectImpl; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java index 7b6aefbe..3554f80a 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java @@ -14,12 +14,12 @@ import java.util.List; import java.util.Optional; +import org.itsallcode.whiterabbit.api.MonthDataStorage; import org.itsallcode.whiterabbit.logic.model.MonthIndex; import org.itsallcode.whiterabbit.logic.model.MultiMonthIndex; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; -import org.itsallcode.whiterabbit.logic.storage.data.MonthDataStorage; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorageTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorageTest.java index af2c976f..dcd9c025 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorageTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorageTest.java @@ -19,8 +19,8 @@ import javax.json.bind.JsonbBuilder; import javax.json.bind.JsonbConfig; +import org.itsallcode.whiterabbit.api.model.MonthData; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; -import org.itsallcode.whiterabbit.logic.model.json.MonthData; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -81,7 +81,7 @@ void loadMonthReturnsMonth_WhenLegacyFileExists() throws IOException when(dateToFileMapperMock.getPathForDate(YEAR_MONTH)).thenReturn(tempDir.resolve("does-not-exist")); when(dateToFileMapperMock.getLegacyPathForDate(YEAR_MONTH)).thenReturn(file); - final Optional loadedMonth = jsonFileStorage.load(YEAR_MONTH); + final Optional loadedMonth = jsonFileStorage.load(YEAR_MONTH); assertThat(loadedMonth).isNotEmpty(); assertThat(loadedMonth.get().getYear()).isEqualTo(2020); } @@ -94,7 +94,7 @@ void loadMonthReturnsMonth_WhenFileExists() throws IOException final Path file = writeTempFile(month); when(dateToFileMapperMock.getPathForDate(YEAR_MONTH)).thenReturn(file); - final Optional loadedMonth = jsonFileStorage.load(YEAR_MONTH); + final Optional loadedMonth = jsonFileStorage.load(YEAR_MONTH); assertThat(loadedMonth).isNotEmpty(); assertThat(loadedMonth.get().getYear()).isEqualTo(2020); } @@ -154,7 +154,7 @@ void loadAll_returnsFiles() throws IOException writeMonth(month1, file1); writeMonth(month2, file2); - final List months = jsonFileStorage.loadAll(); + final List months = jsonFileStorage.loadAll(); assertThat(months).hasSize(2); assertMonth(months.get(0), month1); @@ -176,7 +176,7 @@ void loadAll_sortsByYearMonth() throws IOException writeMonth(month2, file2); writeMonth(month3, file3); - final List months = jsonFileStorage.loadAll(); + final List months = jsonFileStorage.loadAll(); assertThat(months).hasSize(3); assertMonth(months.get(0), month1); From ceba6f01743055ebab94eeb166eeb62e74e030f6 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 6 Feb 2021 16:17:49 +0100 Subject: [PATCH 07/14] Use data storage from plugin if available --- .../whiterabbit/logic/service/AppService.java | 19 +++++++++++++++++-- .../logic/service/plugin/PluginManager.java | 17 +++++++++++++++++ .../logic/storage/CachingStorage.java | 13 +++---------- .../logic/storage/data/DateToFileMapper.java | 4 ++-- .../logic/storage/data/JsonFileStorage.java | 13 ++++++++----- 5 files changed, 47 insertions(+), 19 deletions(-) diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java index 024f4209..df32d113 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java @@ -17,6 +17,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.itsallcode.whiterabbit.api.MonthDataStorage; import org.itsallcode.whiterabbit.api.model.ProjectReport; import org.itsallcode.whiterabbit.logic.Config; import org.itsallcode.whiterabbit.logic.autocomplete.AutocompleteService; @@ -37,6 +38,7 @@ import org.itsallcode.whiterabbit.logic.service.singleinstance.SingleInstanceService; import org.itsallcode.whiterabbit.logic.storage.CachingStorage; import org.itsallcode.whiterabbit.logic.storage.Storage; +import org.itsallcode.whiterabbit.logic.storage.data.JsonFileStorage; public class AppService implements Closeable { @@ -94,8 +96,10 @@ public static AppService create(final Config config, Clock clock, ScheduledExecu { final SingleInstanceService singleInstanceService = SingleInstanceService.create(config); final ProjectService projectService = new ProjectService(config); + final PluginManager pluginManager = PluginManager.create(config); - final CachingStorage storage = CachingStorage.create(config.getDataDir(), new ContractTermsService(config), + final MonthDataStorage dataStorage = createMonthDataStorage(config, pluginManager); + final CachingStorage storage = CachingStorage.create(dataStorage, new ContractTermsService(config), projectService); final ClockService clockService = new ClockService(clock); final AutocompleteService autocompleteService = new AutocompleteService(storage, clockService); @@ -106,13 +110,24 @@ public static AppService create(final Config config, Clock clock, ScheduledExecu final ProjectReportGenerator projectReportGenerator = new ProjectReportGenerator(storage); final ActivityService activityService = new ActivityService(storage, autocompleteService, appServiceCallback); final FormatterService formatterService = new FormatterService(config.getLocale(), clock.getZone()); - final PluginManager pluginManager = PluginManager.create(config); return new AppService(workingTimeService, storage, formatterService, clockService, schedulingService, singleInstanceService, appServiceCallback, activityService, projectService, autocompleteService, new AppPropertiesService(), vacationReportGenerator, projectReportGenerator, pluginManager); } + private static MonthDataStorage createMonthDataStorage(final Config config, final PluginManager pluginManager) + { + final Optional dataStorage = pluginManager.getMonthDataStorage(); + if (dataStorage.isPresent()) + { + LOG.info("Using storage plugin {}", dataStorage.get().getClass().getName()); + return dataStorage.get(); + } + LOG.debug("No storage plugin found, using default json file storage"); + return JsonFileStorage.create(config.getDataDir()); + } + public void setUpdateListener(AppServiceCallback callback) { this.appServiceCallback.setDelegate(callback); diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManager.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManager.java index ba03bda6..efd2eb72 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManager.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManager.java @@ -3,9 +3,11 @@ import static java.util.stream.Collectors.toList; import java.util.List; +import java.util.Optional; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.itsallcode.whiterabbit.api.MonthDataStorage; import org.itsallcode.whiterabbit.api.ProjectReportExporter; import org.itsallcode.whiterabbit.logic.Config; @@ -45,6 +47,21 @@ public ProjectReportExporter getProjectReportExporter(String id) return getFeature(id, ProjectReportExporter.class); } + public Optional getMonthDataStorage() + { + final List pluginIds = findPluginsSupporting(MonthDataStorage.class); + if (pluginIds.isEmpty()) + { + return Optional.empty(); + } + if (pluginIds.size() > 1) + { + throw new IllegalStateException("Found multiple plugins supporting " + MonthDataStorage.class.getName() + + ": " + pluginIds + ". Please add only one storage plugin to the classpath."); + } + return Optional.of(getFeature(pluginIds.get(0), MonthDataStorage.class)); + } + private T getFeature(String id, final Class featureType) { return pluginRegistry.getPlugin(id).getFeature(featureType); diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java index 3d64db28..4fca313e 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java @@ -1,26 +1,19 @@ package org.itsallcode.whiterabbit.logic.storage; -import java.nio.file.Path; import java.time.LocalDate; import java.util.List; -import javax.json.bind.Jsonb; -import javax.json.bind.JsonbBuilder; -import javax.json.bind.JsonbConfig; - import org.itsallcode.whiterabbit.api.MonthDataStorage; import org.itsallcode.whiterabbit.logic.model.DayRecord; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; -import org.itsallcode.whiterabbit.logic.storage.data.JsonFileStorage; public interface CachingStorage extends Storage { - static CachingStorage create(Path dataDir, ContractTermsService contractTerms, ProjectService projectService) + static CachingStorage create(MonthDataStorage dataStorage, ContractTermsService contractTerms, + ProjectService projectService) { - final Jsonb jsonb = JsonbBuilder.create(new JsonbConfig().withFormatting(true)); - final MonthDataStorage fileStorage = new JsonFileStorage(jsonb, dataDir); - final MonthIndexStorage monthIndexStorage = new MonthIndexStorage(contractTerms, projectService, fileStorage); + final MonthIndexStorage monthIndexStorage = new MonthIndexStorage(contractTerms, projectService, dataStorage); return new CachingStorageImpl(monthIndexStorage); } diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/DateToFileMapper.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/DateToFileMapper.java index 7b301358..f130ba51 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/DateToFileMapper.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/DateToFileMapper.java @@ -15,7 +15,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -public class DateToFileMapper +class DateToFileMapper { private static final Logger LOG = LogManager.getLogger(DateToFileMapper.class); @@ -23,7 +23,7 @@ public class DateToFileMapper private final DateTimeFormatter formatter; private final Pattern fileNamePattern = Pattern.compile("^(\\d\\d\\d\\d)-(\\d\\d)\\.json$"); - public DateToFileMapper(Path dataDir) + DateToFileMapper(Path dataDir) { formatter = DateTimeFormatter.ofPattern("yyyy-MM", Locale.ENGLISH); this.dataDir = dataDir; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java index 2c1e88b2..6d75712e 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java @@ -15,6 +15,8 @@ import java.util.Optional; import javax.json.bind.Jsonb; +import javax.json.bind.JsonbBuilder; +import javax.json.bind.JsonbConfig; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -30,17 +32,18 @@ public class JsonFileStorage implements MonthDataStorage private final Jsonb jsonb; private final DateToFileMapper dateToFileMapper; - public JsonFileStorage(Jsonb jsonb, Path dataDir) - { - this(jsonb, new DateToFileMapper(dataDir)); - } - JsonFileStorage(Jsonb jsonb, DateToFileMapper dateToFileMapper) { this.jsonb = jsonb; this.dateToFileMapper = dateToFileMapper; } + public static MonthDataStorage create(Path dataDir) + { + final Jsonb jsonb = JsonbBuilder.create(new JsonbConfig().withFormatting(true)); + return new JsonFileStorage(jsonb, new DateToFileMapper(dataDir)); + } + @Override public Optional load(YearMonth date) { From ca5e0d718a140a7dbda651fe52e85d7043ccb103 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 6 Feb 2021 18:39:01 +0100 Subject: [PATCH 08/14] Fix deserialization of DayData and ActivityData --- .../jfxui/uistate/model/UiStateModelTest.java | 2 - .../jfxui/JavaFxAppUiTestBase.java | 7 ++- logic/build.gradle | 2 +- .../whiterabbit/logic/ConfigLoader.java | 2 +- .../whiterabbit/logic/model/json/JsonDay.java | 1 + .../logic/model/json/JsonbFactory.java | 35 +++++++++++++++ .../logic/storage/data/JsonFileStorage.java | 5 +-- .../storage/data/JsonFileStorageTest.java | 43 +++++++++++++++++-- 8 files changed, 83 insertions(+), 14 deletions(-) create mode 100644 logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonbFactory.java diff --git a/jfxui/src/test/java/org/itsallcode/whiterabbit/jfxui/uistate/model/UiStateModelTest.java b/jfxui/src/test/java/org/itsallcode/whiterabbit/jfxui/uistate/model/UiStateModelTest.java index 3ace3917..3c5a380c 100644 --- a/jfxui/src/test/java/org/itsallcode/whiterabbit/jfxui/uistate/model/UiStateModelTest.java +++ b/jfxui/src/test/java/org/itsallcode/whiterabbit/jfxui/uistate/model/UiStateModelTest.java @@ -118,13 +118,11 @@ void deserializeSplitPaneState() private UiStateModel deserialize(String json) { - final Jsonb jsonb = JsonbBuilder.create(); return jsonb.fromJson(json, UiStateModel.class); } private void assertSerialized(String expectedJson) { - final Jsonb jsonb = JsonbBuilder.create(); final String json = jsonb.toJson(model); assertThat(json).isEqualTo(expectedJson); } diff --git a/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTestBase.java b/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTestBase.java index df05eed3..deb49bd4 100644 --- a/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTestBase.java +++ b/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTestBase.java @@ -18,8 +18,6 @@ import java.util.Objects; import javax.json.bind.Jsonb; -import javax.json.bind.JsonbBuilder; -import javax.json.bind.JsonbConfig; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -28,8 +26,9 @@ import org.itsallcode.whiterabbit.jfxui.testutil.TimeUtil; import org.itsallcode.whiterabbit.jfxui.testutil.model.ApplicationHelper; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; -import org.itsallcode.whiterabbit.logic.service.project.ProjectImpl; +import org.itsallcode.whiterabbit.logic.model.json.JsonbFactory; import org.itsallcode.whiterabbit.logic.service.project.ProjectConfig; +import org.itsallcode.whiterabbit.logic.service.project.ProjectImpl; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.io.TempDir; import org.mockito.junit.jupiter.MockitoExtension; @@ -45,7 +44,7 @@ abstract class JavaFxAppUiTestBase { private static final Logger LOG = LogManager.getLogger(JavaFxAppUiTestBase.class); - private static final Jsonb JSONB = JsonbBuilder.create(new JsonbConfig().withFormatting(true)); + private static final Jsonb JSONB = new JsonbFactory().create(); private JavaFxApp javaFxApp; diff --git a/logic/build.gradle b/logic/build.gradle index def2d479..e4a035a5 100644 --- a/logic/build.gradle +++ b/logic/build.gradle @@ -6,7 +6,7 @@ dependencies { api project(':api') implementation "org.apache.logging.log4j:log4j-api:$log4jVersion" implementation "javax.json.bind:javax.json.bind-api:${jsonBindApiVersion}" - runtimeOnly "org.eclipse:yasson:${yassonVersion}" + implementation "org.eclipse:yasson:${yassonVersion}" } ext.generatedResourcesFolder = file("$buildDir/generated-resources") diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/ConfigLoader.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/ConfigLoader.java index 02bcbe06..50f9325a 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/ConfigLoader.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/ConfigLoader.java @@ -13,8 +13,8 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.itsallcode.whiterabbit.logic.service.project.ProjectImpl; import org.itsallcode.whiterabbit.logic.service.project.ProjectConfig; +import org.itsallcode.whiterabbit.logic.service.project.ProjectImpl; public class ConfigLoader { diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonDay.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonDay.java index f89a36e7..98e1b16b 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonDay.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonDay.java @@ -30,6 +30,7 @@ public class JsonDay implements DayData @JsonbProperty("comment") private String comment; @JsonbProperty("activities") + // @JsonbTypeDeserializer(JsonActivityDeserializer.class) private List activities; @Override diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonbFactory.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonbFactory.java new file mode 100644 index 00000000..ef7f21cf --- /dev/null +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonbFactory.java @@ -0,0 +1,35 @@ +package org.itsallcode.whiterabbit.logic.model.json; + +import java.util.Map; + +import javax.json.bind.Jsonb; +import javax.json.bind.JsonbBuilder; +import javax.json.bind.JsonbConfig; + +import org.eclipse.yasson.YassonConfig; +import org.itsallcode.whiterabbit.api.model.ActivityData; +import org.itsallcode.whiterabbit.api.model.DayData; + +public class JsonbFactory +{ + public Jsonb create() + { + return createWithFormatting(true); + } + + public Jsonb createNonFormatting() + { + return createWithFormatting(false); + } + + private Jsonb createWithFormatting(boolean formatting) + { + final Map, Class> userTypeMapping = Map.of( + DayData.class, JsonDay.class, + ActivityData.class, JsonActivity.class); + final JsonbConfig config = new JsonbConfig() + .withFormatting(formatting) + .setProperty(YassonConfig.USER_TYPE_MAPPING, userTypeMapping); + return JsonbBuilder.create(config); + } +} diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java index 6d75712e..ebe3ccef 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java @@ -15,8 +15,6 @@ import java.util.Optional; import javax.json.bind.Jsonb; -import javax.json.bind.JsonbBuilder; -import javax.json.bind.JsonbConfig; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -24,6 +22,7 @@ import org.itsallcode.whiterabbit.api.model.MonthData; import org.itsallcode.whiterabbit.logic.Config; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; +import org.itsallcode.whiterabbit.logic.model.json.JsonbFactory; public class JsonFileStorage implements MonthDataStorage { @@ -40,7 +39,7 @@ public class JsonFileStorage implements MonthDataStorage public static MonthDataStorage create(Path dataDir) { - final Jsonb jsonb = JsonbBuilder.create(new JsonbConfig().withFormatting(true)); + final Jsonb jsonb = new JsonbFactory().createNonFormatting(); return new JsonFileStorage(jsonb, new DateToFileMapper(dataDir)); } diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorageTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorageTest.java index dcd9c025..20542ca2 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorageTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorageTest.java @@ -16,11 +16,13 @@ import java.util.stream.Stream; import javax.json.bind.Jsonb; -import javax.json.bind.JsonbBuilder; -import javax.json.bind.JsonbConfig; +import org.itsallcode.whiterabbit.api.model.ActivityData; import org.itsallcode.whiterabbit.api.model.MonthData; +import org.itsallcode.whiterabbit.logic.model.json.JsonActivity; +import org.itsallcode.whiterabbit.logic.model.json.JsonDay; import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; +import org.itsallcode.whiterabbit.logic.model.json.JsonbFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -43,7 +45,7 @@ class JsonFileStorageTest @BeforeEach void setUp() { - jsonb = JsonbBuilder.create(new JsonbConfig().withFormatting(false)); + jsonb = new JsonbFactory().createNonFormatting(); jsonFileStorage = new JsonFileStorage(jsonb, dateToFileMapperMock); } @@ -99,6 +101,41 @@ void loadMonthReturnsMonth_WhenFileExists() throws IOException assertThat(loadedMonth.get().getYear()).isEqualTo(2020); } + @Test + void loadMonthReturnsMonth_WithDays() throws IOException + { + final MonthData month = new JsonMonth(); + month.setYear(2020); + final JsonDay day = new JsonDay(); + day.setComment("comment"); + month.setDays(List.of(day)); + final Path file = writeTempFile(month); + + when(dateToFileMapperMock.getPathForDate(YEAR_MONTH)).thenReturn(file); + final Optional loadedMonth = jsonFileStorage.load(YEAR_MONTH); + assertThat(loadedMonth.get().getDays()).hasSize(1); + assertThat(loadedMonth.get().getDays().get(0).getComment()).isEqualTo("comment"); + } + + @Test + void loadMonthReturnsMonth_WithActivities() throws IOException + { + final MonthData month = new JsonMonth(); + month.setYear(2020); + final JsonDay day = new JsonDay(); + final JsonActivity activity = new JsonActivity(); + activity.setProjectId("project"); + day.setActivities(List.of(activity)); + month.setDays(List.of(day)); + final Path file = writeTempFile(month); + + when(dateToFileMapperMock.getPathForDate(YEAR_MONTH)).thenReturn(file); + final Optional loadedMonth = jsonFileStorage.load(YEAR_MONTH); + final List activities = loadedMonth.get().getDays().get(0).getActivities(); + assertThat(activities).hasSize(1); + assertThat(activities.get(0).getProjectId()).isEqualTo("project"); + } + @Test void writeToFile_writesFile() throws IOException { From 36fde312235a5503ddf443c5a0767f314af94dbe Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 6 Feb 2021 18:59:13 +0100 Subject: [PATCH 09/14] Fix sonar badges after project group changed --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c25cad20..2f70a292 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ A time recording tool [![Build](https://github.com/itsallcode/white-rabbit/workflows/Build/badge.svg)](https://github.com/itsallcode/white-rabbit/actions?query=workflow%3ABuild) -[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=white-rabbit&metric=alert_status)](https://sonarcloud.io/dashboard?id=white-rabbit) -[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=white-rabbit&metric=coverage)](https://sonarcloud.io/dashboard?id=white-rabbit) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=org.itsallcode.whiterabbit%3Awhite-rabbit&metric=alert_status)](https://sonarcloud.io/dashboard?id=org.itsallcode.whiterabbit%3Awhite-rabbit) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=org.itsallcode.whiterabbit%3Awhite-rabbit&metric=coverage)](https://sonarcloud.io/dashboard?id=org.itsallcode.whiterabbit%3Awhite-rabbit) * [Features](#features) * [Usage](#usage) From 2ad668cdd50647e75ae58e62626e8f3c60264d4c Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sun, 7 Feb 2021 07:05:36 +0100 Subject: [PATCH 10/14] Allow storage plugin to provide a model factory --- .../whiterabbit/api/MonthDataStorage.java | 13 +++++ .../whiterabbit/api/StorageService.java | 6 --- .../jfxui/JavaFxAppUiTestBase.java | 4 +- .../logic/model/DayActivities.java | 8 +-- .../whiterabbit/logic/model/DayRecord.java | 9 ++-- .../whiterabbit/logic/model/MonthIndex.java | 32 ++++++++---- .../logic/storage/MonthIndexStorage.java | 5 +- .../json => storage/data}/JsonActivity.java | 10 +--- .../{model/json => storage/data}/JsonDay.java | 3 +- .../logic/storage/data/JsonFileStorage.java | 14 ++++-- .../logic/storage/data/JsonModelFactory.java | 27 ++++++++++ .../json => storage/data}/JsonMonth.java | 12 +---- .../json => storage/data}/JsonbFactory.java | 2 +- .../logic/model/DayActivitiesTest.java | 21 ++++---- .../logic/model/DayRecordTest.java | 48 +++++++++--------- .../logic/model/MonthIndexTest.java | 23 +++++---- .../logic/service/ActivityServiceTest.java | 8 +-- .../logic/service/AppServiceTest.java | 50 ++++++++++--------- .../logic/storage/MonthIndexStorageTest.java | 13 +++-- .../storage/data/JsonFileStorageTest.java | 15 ++++-- 20 files changed, 191 insertions(+), 132 deletions(-) delete mode 100644 api/src/main/java/org/itsallcode/whiterabbit/api/StorageService.java rename logic/src/main/java/org/itsallcode/whiterabbit/logic/{model/json => storage/data}/JsonActivity.java (88%) rename logic/src/main/java/org/itsallcode/whiterabbit/logic/{model/json => storage/data}/JsonDay.java (96%) create mode 100644 logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonModelFactory.java rename logic/src/main/java/org/itsallcode/whiterabbit/logic/{model/json => storage/data}/JsonMonth.java (77%) rename logic/src/main/java/org/itsallcode/whiterabbit/logic/{model/json => storage/data}/JsonbFactory.java (94%) diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/MonthDataStorage.java b/api/src/main/java/org/itsallcode/whiterabbit/api/MonthDataStorage.java index 57b1237f..3b11db91 100644 --- a/api/src/main/java/org/itsallcode/whiterabbit/api/MonthDataStorage.java +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/MonthDataStorage.java @@ -4,6 +4,8 @@ import java.util.List; import java.util.Optional; +import org.itsallcode.whiterabbit.api.model.ActivityData; +import org.itsallcode.whiterabbit.api.model.DayData; import org.itsallcode.whiterabbit.api.model.MonthData; public interface MonthDataStorage @@ -15,4 +17,15 @@ public interface MonthDataStorage List getAvailableDataMonths(); List loadAll(); + + ModelFactory getModelFactory(); + + public interface ModelFactory + { + MonthData createMonthData(); + + DayData createDayData(); + + ActivityData createActivityData(); + } } \ No newline at end of file diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/StorageService.java b/api/src/main/java/org/itsallcode/whiterabbit/api/StorageService.java deleted file mode 100644 index e50af177..00000000 --- a/api/src/main/java/org/itsallcode/whiterabbit/api/StorageService.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.itsallcode.whiterabbit.api; - -public interface StorageService -{ - -} diff --git a/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTestBase.java b/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTestBase.java index deb49bd4..ab8ce20f 100644 --- a/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTestBase.java +++ b/jfxui/src/uiTest/java/org/itsallcode/whiterabbit/jfxui/JavaFxAppUiTestBase.java @@ -25,10 +25,10 @@ import org.itsallcode.whiterabbit.jfxui.testutil.TableRowExpectedContent; import org.itsallcode.whiterabbit.jfxui.testutil.TimeUtil; import org.itsallcode.whiterabbit.jfxui.testutil.model.ApplicationHelper; -import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; -import org.itsallcode.whiterabbit.logic.model.json.JsonbFactory; import org.itsallcode.whiterabbit.logic.service.project.ProjectConfig; import org.itsallcode.whiterabbit.logic.service.project.ProjectImpl; +import org.itsallcode.whiterabbit.logic.storage.data.JsonMonth; +import org.itsallcode.whiterabbit.logic.storage.data.JsonbFactory; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.io.TempDir; import org.mockito.junit.jupiter.MockitoExtension; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java index 44bd4f7c..9723e2bd 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java @@ -13,9 +13,9 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.itsallcode.whiterabbit.api.MonthDataStorage.ModelFactory; import org.itsallcode.whiterabbit.api.model.ActivityData; import org.itsallcode.whiterabbit.api.model.DayData; -import org.itsallcode.whiterabbit.logic.model.json.JsonActivity; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; public class DayActivities @@ -23,11 +23,13 @@ public class DayActivities private static final Logger LOG = LogManager.getLogger(DayActivities.class); private final ProjectService projectService; + private final ModelFactory modelFactory; private final DayData day; final DayRecord dayRecord; - DayActivities(DayRecord dayRecord, ProjectService projectService) + DayActivities(DayRecord dayRecord, ProjectService projectService, ModelFactory modelFactory) { + this.modelFactory = modelFactory; this.day = dayRecord.getJsonDay(); this.dayRecord = dayRecord; this.projectService = Objects.requireNonNull(projectService); @@ -41,7 +43,7 @@ public Activity add() } final boolean isFirstActivity = getActivities().findAny().isEmpty(); - final JsonActivity jsonActivity = new JsonActivity(); + final ActivityData jsonActivity = modelFactory.createActivityData(); jsonActivity.setProjectId(""); jsonActivity.setDuration(Duration.ZERO); final int newRowIndex = day.getActivities().size(); diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayRecord.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayRecord.java index ef1e649b..f83174cf 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayRecord.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayRecord.java @@ -8,6 +8,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.itsallcode.whiterabbit.api.MonthDataStorage.ModelFactory; import org.itsallcode.whiterabbit.api.model.DayData; import org.itsallcode.whiterabbit.api.model.DayType; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; @@ -19,18 +20,20 @@ public class DayRecord implements RowRecord private final ContractTermsService contractTerms; private final ProjectService projectService; + private final ModelFactory modelFactory; private final DayData day; private final MonthIndex month; private final DayRecord previousDay; public DayRecord(ContractTermsService contractTerms, DayData day, DayRecord previousDay, MonthIndex month, - ProjectService projectService) + ProjectService projectService, ModelFactory modelFactory) { this.contractTerms = contractTerms; + this.projectService = Objects.requireNonNull(projectService); + this.modelFactory = modelFactory; this.day = day; this.previousDay = previousDay; this.month = month; - this.projectService = Objects.requireNonNull(projectService); } public Duration getMandatoryBreak() @@ -184,7 +187,7 @@ public boolean isDummyDay() public DayActivities activities() { - return new DayActivities(this, projectService); + return new DayActivities(this, projectService, modelFactory); } @Override diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java index b8d35af3..4d362379 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java @@ -10,35 +10,38 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.function.Function; import java.util.stream.Stream; +import org.itsallcode.whiterabbit.api.MonthDataStorage.ModelFactory; import org.itsallcode.whiterabbit.api.model.DayData; import org.itsallcode.whiterabbit.api.model.DayType; import org.itsallcode.whiterabbit.api.model.MonthData; -import org.itsallcode.whiterabbit.logic.model.json.JsonDay; -import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; public class MonthIndex { + private final ModelFactory modelFactory; private final MonthData record; private final Map days; - private MonthIndex(MonthData record, Map days) + private MonthIndex(ModelFactory modelFactory, MonthData record, Map days) { + this.modelFactory = Objects.requireNonNull(modelFactory, "modelFactory"); this.record = record; this.days = days; } - public static MonthIndex create(ContractTermsService contractTerms, ProjectService projectService, MonthData record) + public static MonthIndex create(ContractTermsService contractTerms, ProjectService projectService, + ModelFactory modelFactory, MonthData record) { final Map jsonDays = record.getDays().stream() .collect(toMap(DayData::getDate, Function.identity())); final Map days = new HashMap<>(); - final MonthIndex monthIndex = new MonthIndex(record, days); + final MonthIndex monthIndex = new MonthIndex(modelFactory, record, days); final YearMonth yearMonth = YearMonth.of(record.getYear(), record.getMonth()); @@ -46,8 +49,9 @@ public static MonthIndex create(ContractTermsService contractTerms, ProjectServi for (int day = 1; day <= yearMonth.lengthOfMonth(); day++) { final LocalDate date = yearMonth.atDay(day); - final DayData jsonDay = jsonDays.computeIfAbsent(date, d -> createDummyDay(d, contractTerms)); - final DayRecord dayRecord = new DayRecord(contractTerms, jsonDay, previousDay, monthIndex, projectService); + final DayData jsonDay = jsonDays.computeIfAbsent(date, d -> createDummyDay(d, contractTerms, modelFactory)); + final DayRecord dayRecord = new DayRecord(contractTerms, jsonDay, previousDay, monthIndex, projectService, + modelFactory); days.put(dayRecord.getDate(), dayRecord); previousDay = dayRecord; } @@ -55,9 +59,9 @@ public static MonthIndex create(ContractTermsService contractTerms, ProjectServi return monthIndex; } - private static JsonDay createDummyDay(LocalDate date, ContractTermsService contractTerms) + private static DayData createDummyDay(LocalDate date, ContractTermsService contractTerms, ModelFactory modelFactory) { - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(date); if (contractTerms.getContractedWorkingTimePerDay() != null && !contractTerms.getContractedWorkingTimePerDay().equals(contractTerms.getCurrentWorkingTimePerDay())) @@ -82,13 +86,19 @@ public void put(DayRecord day) this.days.put(day.getDate(), day); } - public JsonMonth getMonthRecord() + public MonthData getMonthRecord() { final List sortedNonDummyJsonDays = getSortedDays() // .filter(d -> !d.isDummyDay()) // .map(DayRecord::getJsonDay) // .collect(toList()); - return JsonMonth.create(record, sortedNonDummyJsonDays); + + final MonthData month = modelFactory.createMonthData(); + month.setOvertimePreviousMonth(record.getOvertimePreviousMonth()); + month.setYear(record.getYear()); + month.setMonth(record.getMonth()); + month.setDays(sortedNonDummyJsonDays); + return month; } public Duration getOvertimePreviousMonth() diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java index ea04e322..4f0843df 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java @@ -15,7 +15,6 @@ import org.itsallcode.whiterabbit.api.model.MonthData; import org.itsallcode.whiterabbit.logic.model.MonthIndex; import org.itsallcode.whiterabbit.logic.model.MultiMonthIndex; -import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; @@ -70,7 +69,7 @@ public List getAvailableDataMonths() private MonthIndex createNewMonth(YearMonth date) { - final MonthData month = new JsonMonth(); + final MonthData month = fileStorage.getModelFactory().createMonthData(); month.setYear(date.getYear()); month.setMonth(date.getMonth()); month.setDays(new ArrayList<>()); @@ -80,7 +79,7 @@ private MonthIndex createNewMonth(YearMonth date) private MonthIndex createMonthIndex(final MonthData jsonMonth) { - return MonthIndex.create(contractTerms, projectService, jsonMonth); + return MonthIndex.create(contractTerms, projectService, fileStorage.getModelFactory(), jsonMonth); } Duration loadPreviousMonthOvertime(YearMonth date) diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonActivity.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonActivity.java similarity index 88% rename from logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonActivity.java rename to logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonActivity.java index db8a1fdd..07cb58b2 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonActivity.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonActivity.java @@ -1,4 +1,4 @@ -package org.itsallcode.whiterabbit.logic.model.json; +package org.itsallcode.whiterabbit.logic.storage.data; import java.time.Duration; @@ -7,6 +7,7 @@ import javax.json.bind.annotation.JsonbVisibility; import org.itsallcode.whiterabbit.api.model.ActivityData; +import org.itsallcode.whiterabbit.logic.model.json.FieldAccessStrategy; @JsonbPropertyOrder({ "projectId", "duration", "comment" }) @JsonbVisibility(FieldAccessStrategy.class) @@ -19,13 +20,6 @@ public class JsonActivity implements ActivityData @JsonbProperty("comment") private String comment; - public JsonActivity() - { - this.projectId = null; - this.duration = null; - this.comment = null; - } - @Override public String getProjectId() { diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonDay.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonDay.java similarity index 96% rename from logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonDay.java rename to logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonDay.java index 98e1b16b..4eadc4c6 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonDay.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonDay.java @@ -1,4 +1,4 @@ -package org.itsallcode.whiterabbit.logic.model.json; +package org.itsallcode.whiterabbit.logic.storage.data; import java.time.Duration; import java.time.LocalDate; @@ -30,7 +30,6 @@ public class JsonDay implements DayData @JsonbProperty("comment") private String comment; @JsonbProperty("activities") - // @JsonbTypeDeserializer(JsonActivityDeserializer.class) private List activities; @Override diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java index ebe3ccef..cdbe81a9 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java @@ -21,8 +21,6 @@ import org.itsallcode.whiterabbit.api.MonthDataStorage; import org.itsallcode.whiterabbit.api.model.MonthData; import org.itsallcode.whiterabbit.logic.Config; -import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; -import org.itsallcode.whiterabbit.logic.model.json.JsonbFactory; public class JsonFileStorage implements MonthDataStorage { @@ -30,17 +28,19 @@ public class JsonFileStorage implements MonthDataStorage private final Jsonb jsonb; private final DateToFileMapper dateToFileMapper; + private final ModelFactory modelFactory; - JsonFileStorage(Jsonb jsonb, DateToFileMapper dateToFileMapper) + JsonFileStorage(Jsonb jsonb, DateToFileMapper dateToFileMapper, ModelFactory modelFactory) { this.jsonb = jsonb; this.dateToFileMapper = dateToFileMapper; + this.modelFactory = modelFactory; } public static MonthDataStorage create(Path dataDir) { final Jsonb jsonb = new JsonbFactory().createNonFormatting(); - return new JsonFileStorage(jsonb, new DateToFileMapper(dataDir)); + return new JsonFileStorage(jsonb, new DateToFileMapper(dataDir), new JsonModelFactory()); } @Override @@ -123,4 +123,10 @@ public List loadAll() .sorted(comparing(JsonMonth::getYear).thenComparing(JsonMonth::getMonth)) .collect(toList()); } + + @Override + public ModelFactory getModelFactory() + { + return modelFactory; + } } diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonModelFactory.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonModelFactory.java new file mode 100644 index 00000000..be3abfac --- /dev/null +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonModelFactory.java @@ -0,0 +1,27 @@ +package org.itsallcode.whiterabbit.logic.storage.data; + +import org.itsallcode.whiterabbit.api.MonthDataStorage.ModelFactory; +import org.itsallcode.whiterabbit.api.model.ActivityData; +import org.itsallcode.whiterabbit.api.model.DayData; +import org.itsallcode.whiterabbit.api.model.MonthData; + +public class JsonModelFactory implements ModelFactory +{ + @Override + public MonthData createMonthData() + { + return new JsonMonth(); + } + + @Override + public DayData createDayData() + { + return new JsonDay(); + } + + @Override + public ActivityData createActivityData() + { + return new JsonActivity(); + } +} diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonMonth.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonMonth.java similarity index 77% rename from logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonMonth.java rename to logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonMonth.java index f0f81d02..ba204c78 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonMonth.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonMonth.java @@ -1,4 +1,4 @@ -package org.itsallcode.whiterabbit.logic.model.json; +package org.itsallcode.whiterabbit.logic.storage.data; import java.time.Duration; import java.time.Month; @@ -22,16 +22,6 @@ public class JsonMonth implements MonthData @JsonbProperty("days") private List days; - public static JsonMonth create(MonthData record, List sortedDays) - { - final JsonMonth month = new JsonMonth(); - month.setOvertimePreviousMonth(record.getOvertimePreviousMonth()); - month.setYear(record.getYear()); - month.setMonth(record.getMonth()); - month.setDays(sortedDays); - return month; - } - @Override public int getYear() { diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonbFactory.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonbFactory.java similarity index 94% rename from logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonbFactory.java rename to logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonbFactory.java index ef7f21cf..263912d1 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/json/JsonbFactory.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonbFactory.java @@ -1,4 +1,4 @@ -package org.itsallcode.whiterabbit.logic.model.json; +package org.itsallcode.whiterabbit.logic.storage.data; import java.util.Map; diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayActivitiesTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayActivitiesTest.java index 06d660bb..26cf1d9c 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayActivitiesTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayActivitiesTest.java @@ -8,11 +8,12 @@ import java.time.Duration; import java.util.ArrayList; +import org.itsallcode.whiterabbit.api.MonthDataStorage.ModelFactory; import org.itsallcode.whiterabbit.api.model.ActivityData; -import org.itsallcode.whiterabbit.logic.model.json.JsonActivity; -import org.itsallcode.whiterabbit.logic.model.json.JsonDay; +import org.itsallcode.whiterabbit.api.model.DayData; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; +import org.itsallcode.whiterabbit.logic.storage.data.JsonModelFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -26,13 +27,15 @@ class DayActivitiesTest private ProjectService projectServiceMock; @Mock private ContractTermsService contractTermsMock; - private JsonDay jsonDay; + private ModelFactory modelFactory; + private DayData jsonDay; private DayRecord dayRecord; @BeforeEach void setup() { - jsonDay = new JsonDay(); + modelFactory = new JsonModelFactory(); + jsonDay = modelFactory.createDayData(); } @Test @@ -283,7 +286,7 @@ void setRemainderToFalse() when(contractTermsMock.getWorkingTime(same(dayRecord))).thenReturn(Duration.ofHours(7)); - final ActivityData activity = new JsonActivity(); + final ActivityData activity = modelFactory.createActivityData(); activity.setDuration(null); activities.setRemainderActivity(activity, false); @@ -300,7 +303,7 @@ void setRemainderToFalseSetsRemainingDuration() when(contractTermsMock.getWorkingTime(same(dayRecord))).thenReturn(Duration.ofHours(7)); activities.add().setDuration(Duration.ofHours(3)); - final ActivityData activity = new JsonActivity(); + final ActivityData activity = modelFactory.createActivityData(); activity.setDuration(null); activities.setRemainderActivity(activity, false); @@ -318,7 +321,7 @@ void setRemainderToFalseSetsRemainingDurationMultipleActivities() activities.add().setDuration(Duration.ofHours(3)); activities.add().setDuration(Duration.ofMinutes(30)); - final ActivityData activity = new JsonActivity(); + final ActivityData activity = modelFactory.createActivityData(); activity.setDuration(null); activities.setRemainderActivity(activity, false); @@ -331,7 +334,7 @@ private DayActivities create() { final DayRecord previousDay = null; final MonthIndex month = null; - dayRecord = new DayRecord(contractTermsMock, jsonDay, previousDay, month, projectServiceMock); - return new DayActivities(dayRecord, projectServiceMock); + dayRecord = new DayRecord(contractTermsMock, jsonDay, previousDay, month, projectServiceMock, modelFactory); + return new DayActivities(dayRecord, projectServiceMock, modelFactory); } } diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java index 91e296b5..2d1e367f 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java @@ -8,13 +8,14 @@ import java.time.LocalDate; import java.time.LocalTime; +import org.itsallcode.whiterabbit.api.MonthDataStorage.ModelFactory; +import org.itsallcode.whiterabbit.api.model.DayData; import org.itsallcode.whiterabbit.api.model.DayType; import org.itsallcode.whiterabbit.api.model.MonthData; import org.itsallcode.whiterabbit.logic.Config; -import org.itsallcode.whiterabbit.logic.model.json.JsonDay; -import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; +import org.itsallcode.whiterabbit.logic.storage.data.JsonModelFactory; import org.itsallcode.whiterabbit.logic.test.TestingConfig; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -26,6 +27,7 @@ class DayRecordTest { @Mock private ProjectService projectServiceMock; + private final ModelFactory modelFactory = new JsonModelFactory(); @Test void mandatoryWorkingTimeIsZeroOnWeekend() @@ -324,7 +326,7 @@ void setInterruptionFailsForNullValue() @Test void setInterruptionToZeroUsesNullForJsonRecord() { - final JsonDay day1 = new JsonDay(); + final DayData day1 = modelFactory.createDayData(); day1.setInterruption(Duration.ofHours(1)); final DayRecord day = dayRecord(day1, null, null); @@ -337,7 +339,7 @@ void setInterruptionToZeroUsesNullForJsonRecord() @Test void setCommentToEmptyStringUsesNullForJsonRecord() { - final JsonDay day1 = new JsonDay(); + final DayData day1 = modelFactory.createDayData(); day1.setComment("comment"); final DayRecord day = dayRecord(day1, null, null); @@ -350,7 +352,7 @@ void setCommentToEmptyStringUsesNullForJsonRecord() @Test void setCommentToValueSetsCommentForJsonRecord() { - final JsonDay day1 = new JsonDay(); + final DayData day1 = modelFactory.createDayData(); final DayRecord day = dayRecord(day1, null, null); day.setComment("comment"); @@ -400,41 +402,41 @@ void getMonthReturnsMonth() } @Test - void getJsonDayReturnsMonth() + void getDayDataReturnsMonth() { - final JsonDay jsonDay = new JsonDay(); - final DayRecord day = createDay(jsonDay); - assertThat(day.getJsonDay()).isSameAs(jsonDay); + final DayData dayData = modelFactory.createDayData(); + final DayRecord day = createDay(dayData); + assertThat(day.getJsonDay()).isSameAs(dayData); } @Test void getCustomWorkingTimeReturnsEmptyOptionalByDefault() { - final JsonDay jsonDay = new JsonDay(); - jsonDay.setWorkingHours(null); + final DayData DayData = modelFactory.createDayData(); + DayData.setWorkingHours(null); - final DayRecord day = createDay(jsonDay); + final DayRecord day = createDay(DayData); assertThat(day.getCustomWorkingTime()).isEmpty(); } @Test void getCustomWorkingTimeReturnsRealValue() { - final JsonDay jsonDay = new JsonDay(); - jsonDay.setWorkingHours(Duration.ofHours(5)); + final DayData DayData = modelFactory.createDayData(); + DayData.setWorkingHours(Duration.ofHours(5)); - final DayRecord day = createDay(jsonDay); + final DayRecord day = createDay(DayData); assertThat(day.getCustomWorkingTime()).isPresent().contains(Duration.ofHours(5)); } - private MonthIndex month(LocalDate date, Duration overtimePreviousMonth, JsonDay... days) + private MonthIndex month(LocalDate date, Duration overtimePreviousMonth, DayData... days) { - final MonthData jsonMonth = new JsonMonth(); + final MonthData jsonMonth = modelFactory.createMonthData(); jsonMonth.setDays(asList(days)); jsonMonth.setMonth(date.getMonth()); jsonMonth.setYear(date.getYear()); jsonMonth.setOvertimePreviousMonth(overtimePreviousMonth); - return MonthIndex.create(contractTerms(), projectServiceMock, jsonMonth); + return MonthIndex.create(contractTerms(), projectServiceMock, modelFactory, jsonMonth); } private void assertOvertime(LocalDate date, LocalTime begin, LocalTime end, Duration expectedOvertime) @@ -518,7 +520,7 @@ private DayRecord createDay(LocalDate date, LocalTime begin, LocalTime end, DayT private DayRecord createDay(LocalDate date, LocalTime begin, LocalTime end, DayType type, Duration interruption, DayRecord previousDay, MonthIndex month) { - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setBegin(begin); day.setEnd(end); day.setDate(date); @@ -528,15 +530,15 @@ private DayRecord createDay(LocalDate date, LocalTime begin, LocalTime end, DayT return dayRecord(day, previousDay, month); } - private DayRecord createDay(final JsonDay jsonDay) + private DayRecord createDay(final DayData DayData) { - return new DayRecord(null, jsonDay, null, null, projectServiceMock); + return new DayRecord(null, DayData, null, null, projectServiceMock, modelFactory); } - private DayRecord dayRecord(JsonDay day, DayRecord previousDay, MonthIndex month) + private DayRecord dayRecord(DayData day, DayRecord previousDay, MonthIndex month) { final ContractTermsService contractTerms = contractTerms(); - return new DayRecord(contractTerms, day, previousDay, month, projectServiceMock); + return new DayRecord(contractTerms, day, previousDay, month, projectServiceMock, modelFactory); } private ContractTermsService contractTerms() diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java index a32a702e..44cef575 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java @@ -9,13 +9,14 @@ import java.time.Month; import java.time.YearMonth; +import org.itsallcode.whiterabbit.api.MonthDataStorage.ModelFactory; +import org.itsallcode.whiterabbit.api.model.DayData; import org.itsallcode.whiterabbit.api.model.DayType; import org.itsallcode.whiterabbit.api.model.MonthData; import org.itsallcode.whiterabbit.logic.Config; -import org.itsallcode.whiterabbit.logic.model.json.JsonDay; -import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; +import org.itsallcode.whiterabbit.logic.storage.data.JsonModelFactory; import org.itsallcode.whiterabbit.logic.test.TestingConfig; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -28,6 +29,8 @@ class MonthIndexTest @Mock private ProjectService projectServiceMock; + private final ModelFactory modelFactory = new JsonModelFactory(); + @Test void testCalculateTotalOvertimeOvertimeNoDays() { @@ -163,24 +166,24 @@ void newDaysHaveCustomWorkingTimeWhenCurrentHoursPerDayAreConfigured() assertThat(day.getCustomWorkingTime()).isPresent().contains(Duration.ofHours(5)); } - private Duration calculateTotalOvertime(JsonDay... days) + private Duration calculateTotalOvertime(DayData... days) { return calculateTotalOvertime(null, days); } - private Duration calculateTotalOvertime(Duration overtimePreviousMonth, JsonDay... days) + private Duration calculateTotalOvertime(Duration overtimePreviousMonth, DayData... days) { return create(jsonMonth(overtimePreviousMonth, days)).getTotalOvertime(); } - private MonthData jsonMonth(Duration overtimePreviousMonth, JsonDay... days) + private MonthData jsonMonth(Duration overtimePreviousMonth, DayData... days) { return jsonMonth(YearMonth.of(2019, Month.MAY), overtimePreviousMonth, days); } - private MonthData jsonMonth(YearMonth yearMonth, Duration overtimePreviousMonth, JsonDay... days) + private MonthData jsonMonth(YearMonth yearMonth, Duration overtimePreviousMonth, DayData... days) { - final MonthData month = new JsonMonth(); + final MonthData month = modelFactory.createMonthData(); month.setYear(yearMonth.getYear()); month.setMonth(yearMonth.getMonth()); month.setDays(asList(days)); @@ -188,12 +191,12 @@ private MonthData jsonMonth(YearMonth yearMonth, Duration overtimePreviousMonth, return month; } - private JsonDay day(Duration overtime, int dayOfMonth) + private DayData day(Duration overtime, int dayOfMonth) { final LocalTime begin = LocalTime.of(8, 0); final LocalTime end = begin.plus(Duration.ofHours(8)).plus(Duration.ofMinutes(45).plus(overtime)); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(LocalDate.of(2019, Month.MAY, dayOfMonth)); day.setBegin(begin); day.setEnd(end); @@ -208,6 +211,6 @@ private MonthIndex create(MonthData record) private MonthIndex create(Config config, MonthData record) { - return MonthIndex.create(new ContractTermsService(config), projectServiceMock, record); + return MonthIndex.create(new ContractTermsService(config), projectServiceMock, modelFactory, record); } } diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ActivityServiceTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ActivityServiceTest.java index 9199eb27..954ac473 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ActivityServiceTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ActivityServiceTest.java @@ -17,11 +17,11 @@ import org.itsallcode.whiterabbit.api.model.MonthData; import org.itsallcode.whiterabbit.logic.autocomplete.AutocompleteService; import org.itsallcode.whiterabbit.logic.model.MonthIndex; -import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectImpl; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; import org.itsallcode.whiterabbit.logic.storage.Storage; +import org.itsallcode.whiterabbit.logic.storage.data.JsonModelFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -42,6 +42,7 @@ class ActivityServiceTest private ProjectService projectService; @Mock private AutocompleteService autocompleteServiceMock; + private JsonModelFactory modelFactory; private ActivityService service; @@ -49,6 +50,7 @@ class ActivityServiceTest void setUp() { service = new ActivityService(storageMock, autocompleteServiceMock, appServiceCallbackMock); + modelFactory = new JsonModelFactory(); } @Test @@ -127,10 +129,10 @@ void removeActivity() private MonthIndex createMonth() { - final MonthData monthRecord = new JsonMonth(); + final MonthData monthRecord = modelFactory.createMonthData(); monthRecord.setDays(new ArrayList<>()); monthRecord.setYear(DATE.getYear()); monthRecord.setMonth(DATE.getMonth()); - return MonthIndex.create(contractTermsServiceMock, projectService, monthRecord); + return MonthIndex.create(contractTermsServiceMock, projectService, modelFactory, monthRecord); } } diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/AppServiceTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/AppServiceTest.java index 35811c61..34d78b01 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/AppServiceTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/AppServiceTest.java @@ -21,11 +21,11 @@ import java.time.ZoneOffset; import java.time.temporal.ChronoUnit; +import org.itsallcode.whiterabbit.api.model.DayData; import org.itsallcode.whiterabbit.logic.Config; import org.itsallcode.whiterabbit.logic.autocomplete.AutocompleteService; import org.itsallcode.whiterabbit.logic.model.DayRecord; import org.itsallcode.whiterabbit.logic.model.MonthIndex; -import org.itsallcode.whiterabbit.logic.model.json.JsonDay; import org.itsallcode.whiterabbit.logic.report.project.ProjectReportGenerator; import org.itsallcode.whiterabbit.logic.report.vacation.VacationReportGenerator; import org.itsallcode.whiterabbit.logic.service.AppPropertiesService.AppProperties; @@ -39,6 +39,7 @@ import org.itsallcode.whiterabbit.logic.service.singleinstance.RunningInstanceCallback; import org.itsallcode.whiterabbit.logic.service.singleinstance.SingleInstanceService; import org.itsallcode.whiterabbit.logic.storage.Storage; +import org.itsallcode.whiterabbit.logic.storage.data.JsonModelFactory; import org.itsallcode.whiterabbit.logic.test.TestingConfig; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -85,6 +86,8 @@ class AppServiceTest private AppService appService; + private JsonModelFactory modelFactory; + @BeforeEach void setUp() { @@ -96,6 +99,7 @@ void setUp() autocompleteServiceMock, appPropertiesServiceMock, vacationReportGeneratorMock, projectReportGeneratorMock, pluginManagerMock); appService.setUpdateListener(updateListenerMock); + modelFactory = new JsonModelFactory(); } @Test @@ -103,7 +107,7 @@ void testNoUpdateWhenNotWorkingDay() { final LocalTime now = LocalTime.of(14, 0); final LocalDate today = LocalDate.of(2019, 3, 9); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); updateNow(now, day); @@ -117,7 +121,7 @@ void testUpdateListenerNotCalledWhenNoUpdate() { final LocalTime now = LocalTime.of(14, 0); final LocalDate today = LocalDate.of(2019, 3, 9); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); updateNow(now, day); @@ -130,7 +134,7 @@ void testUpdateListenerCalledWhenDayRecordUpdated() { final LocalTime now = LocalTime.of(8, 0); final LocalDate today = LocalDate.of(2019, 3, 8); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); final DayRecord updatedRecord = updateNow(now, day); @@ -143,7 +147,7 @@ void testUpdateNewDayOnWorkingDay() { final LocalTime now = LocalTime.of(8, 0); final LocalDate today = LocalDate.of(2019, 3, 8); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); updateNow(now, day); @@ -158,7 +162,7 @@ void testUpdateExistingDayAfter1Min() final LocalTime begin = LocalTime.of(8, 0); final LocalTime now = LocalTime.of(8, 1); final LocalDate today = LocalDate.of(2019, 3, 8); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); day.setBegin(begin); day.setEnd(begin); @@ -175,7 +179,7 @@ void testUpdateExistingDayAfter2Min() final LocalTime begin = LocalTime.of(8, 0); final LocalTime now = LocalTime.of(8, 2); final LocalDate today = LocalDate.of(2019, 3, 8); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); day.setBegin(begin); day.setEnd(begin); @@ -196,7 +200,7 @@ void testNoUpdateIfEndAfterNow() final LocalTime end = LocalTime.of(16, 0); final LocalTime now = LocalTime.of(9, 0); final LocalDate today = LocalDate.of(2019, 3, 8); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); day.setBegin(begin); day.setEnd(end); @@ -213,7 +217,7 @@ void testUpdateExistingDayAfter3Min() final LocalTime begin = LocalTime.of(8, 0); final LocalTime now = LocalTime.of(8, 3); final LocalDate today = LocalDate.of(2019, 3, 8); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); day.setBegin(begin); day.setEnd(begin); @@ -232,7 +236,7 @@ void testUpdateNowAddsInterruption() { final LocalTime now = LocalTime.of(14, 0); final LocalDate today = LocalDate.of(2019, 3, 8); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); day.setBegin(LocalTime.of(8, 0)); day.setEnd(LocalTime.of(13, 0)); @@ -251,7 +255,7 @@ void testUpdateNowDoesNotAddInterruptionWhenCallbackSaysNo() { final LocalTime now = LocalTime.of(14, 0); final LocalDate today = LocalDate.of(2019, 3, 8); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); day.setBegin(LocalTime.of(8, 0)); day.setEnd(LocalTime.of(13, 0)); @@ -271,7 +275,7 @@ void testUpdateNowDoesNotAddInterruptionWhenCallbackStopWorkForToday() final LocalTime beforeInterruption = LocalTime.of(13, 0); final LocalTime now = beforeInterruption.plusHours(1); final LocalDate today = LocalDate.of(2019, 3, 8); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); day.setBegin(LocalTime.of(8, 0)); day.setEnd(beforeInterruption); @@ -290,7 +294,7 @@ void testUpdateDoesNotUpdateBeginIfInThePast() { final LocalTime now = LocalTime.of(9, 0); final LocalDate today = LocalDate.of(2019, 3, 8); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); final LocalTime begin = LocalTime.of(8, 0); day.setBegin(begin); @@ -307,7 +311,7 @@ void testUpdateDoesUpdateBeginIfInTheFuture() { final LocalTime now = LocalTime.of(9, 0); final LocalDate today = LocalDate.of(2019, 3, 8); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); final LocalTime begin = LocalTime.of(10, 0); day.setBegin(begin); @@ -324,7 +328,7 @@ void testUpdateNowDoesNotAddInterruptionIfAlreadyRunning() { final LocalTime now = LocalTime.of(14, 0); final LocalDate today = LocalDate.of(2019, 3, 8); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); day.setBegin(LocalTime.of(8, 0)); day.setEnd(LocalTime.of(13, 0)); @@ -344,7 +348,7 @@ void addInterruptionCallback() { final LocalTime now = LocalTime.of(14, 0); final LocalDate today = LocalDate.of(2019, 3, 8); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); day.setBegin(LocalTime.of(8, 0)); day.setEnd(LocalTime.of(13, 0)); @@ -368,7 +372,7 @@ void cancelInterruptionCallback() { final LocalTime now = LocalTime.of(14, 0); final LocalDate today = LocalDate.of(2019, 3, 8); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); day.setBegin(LocalTime.of(8, 0)); day.setEnd(LocalTime.of(13, 0)); @@ -434,7 +438,7 @@ void toggleStopWorkForTodayCurrentlyNotStopped() { final LocalTime now = LocalTime.of(14, 0); final LocalDate today = LocalDate.of(2019, 3, 8); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); day.setBegin(LocalTime.of(8, 0)); day.setEnd(now); @@ -450,7 +454,7 @@ void toggleStopWorkForTodayAlreadyStopped() { final LocalTime now = LocalTime.of(14, 0); final LocalDate today = LocalDate.of(2019, 3, 8); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); day.setBegin(LocalTime.of(8, 0)); day.setEnd(now); @@ -468,7 +472,7 @@ void endTimeNotUpdatedWhenWorkStoppedForToday() { final LocalTime now = LocalTime.of(14, 0); final LocalDate today = LocalDate.of(2019, 3, 8); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); day.setBegin(LocalTime.of(8, 0)); day.setEnd(now); @@ -491,7 +495,7 @@ void endTimeNotUpdatedWhenWorkNotStoppedForToday() { final LocalTime now = LocalTime.of(14, 0); final LocalDate today = LocalDate.of(2019, 3, 8); - final JsonDay day = new JsonDay(); + final DayData day = modelFactory.createDayData(); day.setDate(today); day.setBegin(LocalTime.of(8, 0)); day.setEnd(now); @@ -519,13 +523,13 @@ void loadAppProperties() assertThat(appService.getAppProperties()).isSameAs(appPropertiesMock); } - private DayRecord updateNow(final LocalTime now, final JsonDay day) + private DayRecord updateNow(final LocalTime now, final DayData day) { when(clockMock.getCurrentDate()).thenReturn(day.getDate()); when(clockMock.getCurrentTime()).thenReturn(now); when(storageMock.loadOrCreate(YearMonth.from(day.getDate()))).thenReturn(monthIndexMock); final DayRecord dayRecord = new DayRecord(new ContractTermsService(TestingConfig.builder().build()), day, null, - monthIndexMock, projectServiceMock); + monthIndexMock, projectServiceMock, modelFactory); when(monthIndexMock.getDay(day.getDate())).thenReturn(dayRecord); appService.updateNow(); diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java index 3554f80a..5c2f0018 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java @@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -15,11 +16,12 @@ import java.util.Optional; import org.itsallcode.whiterabbit.api.MonthDataStorage; +import org.itsallcode.whiterabbit.api.model.MonthData; import org.itsallcode.whiterabbit.logic.model.MonthIndex; import org.itsallcode.whiterabbit.logic.model.MultiMonthIndex; -import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; +import org.itsallcode.whiterabbit.logic.storage.data.JsonModelFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -47,6 +49,7 @@ class MonthIndexStorageTest void setUp() { storage = new MonthIndexStorage(contractTermsMock, projectServiceMock, fileStorageMock); + lenient().when(fileStorageMock.getModelFactory()).thenReturn(new JsonModelFactory()); } @Test @@ -91,7 +94,7 @@ void loadOrCreate_createsNewMonthIfNotExists() @Test void loadOrCreate_loadsExistingMonth() { - final JsonMonth month = jsonMonth(YEAR_MONTH, Duration.ofMinutes(4)); + final MonthData month = jsonMonth(YEAR_MONTH, Duration.ofMinutes(4)); when(fileStorageMock.load(YEAR_MONTH)).thenReturn(Optional.of(month)); final MonthIndex newMonth = storage.loadOrCreate(YEAR_MONTH); @@ -106,7 +109,7 @@ void loadOrCreate_loadsExistingMonth() @Test void storeMonth() { - final JsonMonth month = jsonMonth(YEAR_MONTH, Duration.ofMinutes(4)); + final MonthData month = jsonMonth(YEAR_MONTH, Duration.ofMinutes(4)); when(monthIndexMock.getMonthRecord()).thenReturn(month); when(monthIndexMock.getYearMonth()).thenReturn(YEAR_MONTH); @@ -146,9 +149,9 @@ void getAvailableDataYearMonth() assertThat(storage.getAvailableDataMonths()).isSameAs(availableYearMonths); } - private JsonMonth jsonMonth(YearMonth yearMonth, Duration overtimePreviousMonth) + private MonthData jsonMonth(YearMonth yearMonth, Duration overtimePreviousMonth) { - final JsonMonth month = new JsonMonth(); + final MonthData month = new JsonModelFactory().createMonthData(); month.setYear(yearMonth.getYear()); month.setMonth(yearMonth.getMonth()); month.setOvertimePreviousMonth(overtimePreviousMonth); diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorageTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorageTest.java index 20542ca2..932c1e74 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorageTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorageTest.java @@ -17,12 +17,9 @@ import javax.json.bind.Jsonb; +import org.itsallcode.whiterabbit.api.MonthDataStorage.ModelFactory; import org.itsallcode.whiterabbit.api.model.ActivityData; import org.itsallcode.whiterabbit.api.model.MonthData; -import org.itsallcode.whiterabbit.logic.model.json.JsonActivity; -import org.itsallcode.whiterabbit.logic.model.json.JsonDay; -import org.itsallcode.whiterabbit.logic.model.json.JsonMonth; -import org.itsallcode.whiterabbit.logic.model.json.JsonbFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -38,6 +35,8 @@ class JsonFileStorageTest Path tempDir; @Mock DateToFileMapper dateToFileMapperMock; + @Mock + private ModelFactory modelFactoryMock; JsonFileStorage jsonFileStorage; Jsonb jsonb; @@ -46,7 +45,7 @@ class JsonFileStorageTest void setUp() { jsonb = new JsonbFactory().createNonFormatting(); - jsonFileStorage = new JsonFileStorage(jsonb, dateToFileMapperMock); + jsonFileStorage = new JsonFileStorage(jsonb, dateToFileMapperMock, modelFactoryMock); } @Test @@ -221,6 +220,12 @@ void loadAll_sortsByYearMonth() throws IOException assertMonth(months.get(2), month3); } + @Test + void getModelFactory() + { + assertThat(jsonFileStorage.getModelFactory()).isSameAs(modelFactoryMock); + } + private void assertMonth(MonthData actual, MonthData expected) { assertAll(() -> assertThat(actual.getYear()).isEqualTo(expected.getYear()), From b5ba3898b39daccfcbeb99da44440ee8b7b3d0b1 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sun, 7 Feb 2021 08:48:36 +0100 Subject: [PATCH 11/14] Add unit tests for AppService --- .../whiterabbit/logic/service/AppService.java | 14 +- .../logic/service/DayReporter.java | 1 + .../logic/service/plugin/PluginRegistry.java | 2 +- .../logic/service/project/ProjectService.java | 2 +- .../logic/service/AppServiceTest.java | 238 +++++++++++++++++- 5 files changed, 239 insertions(+), 18 deletions(-) diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java index df32d113..d764592e 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java @@ -1,6 +1,5 @@ package org.itsallcode.whiterabbit.logic.service; -import static java.util.Collections.emptyList; import static java.util.stream.Collectors.toList; import java.io.Closeable; @@ -170,6 +169,7 @@ public SchedulingService scheduler() return this.schedulingService; } + @Deprecated public void report() { final DayReporter reporter = new DayReporter(formatterService); @@ -197,23 +197,11 @@ public ClockService getClock() return clock; } - public List getRecords(YearMonth yearMonth) - { - return getMonth(yearMonth) // - .map(record -> record.getSortedDays().collect(toList())) // - .orElse(emptyList()); - } - public List getAvailableDataYearMonth() { return storage.getAvailableDataMonths(); } - public Optional getMonth(YearMonth yearMonth) - { - return storage.loadMonth(yearMonth); - } - public MonthIndex getOrCreateMonth(YearMonth yearMonth) { return storage.loadOrCreate(yearMonth); diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/DayReporter.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/DayReporter.java index 0649e0d6..c2acf880 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/DayReporter.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/DayReporter.java @@ -6,6 +6,7 @@ import org.apache.logging.log4j.Logger; import org.itsallcode.whiterabbit.logic.model.DayRecord; +@Deprecated public class DayReporter { private static final Logger LOG = LogManager.getLogger(DayReporter.class); diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginRegistry.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginRegistry.java index ec0af087..f34d7806 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginRegistry.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginRegistry.java @@ -95,7 +95,7 @@ private ClassLoader createClassLoader(Path jar) private List getPluginJars() { final Path pluginDir = config.getPluginDir(); - if (!Files.exists(pluginDir)) + if (pluginDir == null || !Files.exists(pluginDir)) { LOG.info("Plugin directory {} does not exist", pluginDir); return emptyList(); diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/project/ProjectService.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/project/ProjectService.java index d5ed6041..cda8d919 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/project/ProjectService.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/project/ProjectService.java @@ -41,7 +41,7 @@ public ProjectService(Config config) this.jsonb = jsonb; final Path projectConfigFile = config.getProjectFile(); - if (Files.exists(projectConfigFile)) + if (projectConfigFile != null && Files.exists(projectConfigFile)) { final List allProjects = loadAvailableProjects(projectConfigFile); projectsById = groupBy(allProjects, ProjectImpl::getProjectId); diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/AppServiceTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/AppServiceTest.java index 34d78b01..6bdd6d9e 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/AppServiceTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/AppServiceTest.java @@ -1,5 +1,6 @@ package org.itsallcode.whiterabbit.logic.service; +import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -7,6 +8,7 @@ import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; @@ -17,16 +19,23 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; +import java.time.Month; import java.time.YearMonth; import java.time.ZoneOffset; import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.Locale; import org.itsallcode.whiterabbit.api.model.DayData; +import org.itsallcode.whiterabbit.api.model.MonthData; +import org.itsallcode.whiterabbit.api.model.ProjectReport; import org.itsallcode.whiterabbit.logic.Config; import org.itsallcode.whiterabbit.logic.autocomplete.AutocompleteService; import org.itsallcode.whiterabbit.logic.model.DayRecord; import org.itsallcode.whiterabbit.logic.model.MonthIndex; +import org.itsallcode.whiterabbit.logic.model.MultiMonthIndex; import org.itsallcode.whiterabbit.logic.report.project.ProjectReportGenerator; +import org.itsallcode.whiterabbit.logic.report.vacation.VacationReport; import org.itsallcode.whiterabbit.logic.report.vacation.VacationReportGenerator; import org.itsallcode.whiterabbit.logic.service.AppPropertiesService.AppProperties; import org.itsallcode.whiterabbit.logic.service.AppServiceCallback.InterruptionDetectedDecision; @@ -83,6 +92,10 @@ class AppServiceTest private AutocompleteService autocompleteServiceMock; @Mock private PluginManager pluginManagerMock; + @Mock + private WorkingTimeService workingTimeServiceMock; + + private ContractTermsService contractTerms; private AppService appService; @@ -94,12 +107,26 @@ void setUp() final DelegatingAppServiceCallback appServiceCallback = new DelegatingAppServiceCallback(); final WorkingTimeService workingTimeService = new WorkingTimeService(storageMock, clockMock, appServiceCallback); - appService = new AppService(workingTimeService, storageMock, formatterServiceMock, clockMock, + appService = createAppService(appServiceCallback, workingTimeService); + appService.setUpdateListener(updateListenerMock); + modelFactory = new JsonModelFactory(); + contractTerms = new ContractTermsService(configMock); + } + + private AppService createAppService(final DelegatingAppServiceCallback appServiceCallback, + final WorkingTimeService workingTimeService) + { + return new AppService(workingTimeService, storageMock, formatterServiceMock, clockMock, schedulingServiceMock, singleInstanceService, appServiceCallback, activityService, projectServiceMock, autocompleteServiceMock, appPropertiesServiceMock, vacationReportGeneratorMock, projectReportGeneratorMock, pluginManagerMock); - appService.setUpdateListener(updateListenerMock); - modelFactory = new JsonModelFactory(); + } + + @Test + void create() + { + when(configMock.getLocale()).thenReturn(Locale.ENGLISH); + assertThat(AppService.create(configMock)).isNotNull(); } @Test @@ -523,6 +550,88 @@ void loadAppProperties() assertThat(appService.getAppProperties()).isSameAs(appPropertiesMock); } + @Test + void updatePreviousMonthOvertimeField_noMonth() + { + simulateStorageLoadAll(); + appService.updatePreviousMonthOvertimeField(); + verify(storageMock, never()).storeMonth(any()); + } + + @Test + void updatePreviousMonthOvertimeField_singleMonthNoDays() + { + final MonthIndex month1 = monthIndex(YearMonth.of(2021, 1)); + simulateStorageLoadAll(month1); + appService.updatePreviousMonthOvertimeField(); + + verify(storageMock).storeMonth(same(month1)); + assertThat(month1.getOvertimePreviousMonth()).isZero(); + } + + @Test + void updatePreviousMonthOvertimeField_singleMonthWithDays() + { + final MonthIndex month1 = monthIndex(YearMonth.of(2021, 1), + day(LocalDate.of(2021, 1, 1), Duration.ofMinutes(10))); + simulateStorageLoadAll(month1); + appService.updatePreviousMonthOvertimeField(); + + assertThat(month1.getOvertimePreviousMonth()).isZero(); + } + + @Test + void updatePreviousMonthOvertimeField_twoMonthWithSingleDay() + { + final MonthIndex month1 = monthIndex(YearMonth.of(2021, 1), + day(LocalDate.of(2021, 1, 1), Duration.ofMinutes(10))); + final MonthIndex month2 = monthIndex(YearMonth.of(2021, 2), + day(LocalDate.of(2021, 2, 1), Duration.ofMinutes(20))); + simulateStorageLoadAll(month1, month2); + appService.updatePreviousMonthOvertimeField(); + + assertThat(month1.getOvertimePreviousMonth()).isZero(); + assertThat(month2.getOvertimePreviousMonth()).isEqualTo(Duration.ofMinutes(10)); + } + + @Test + void updatePreviousMonthOvertimeField_twoMonthWithMultipleDays() + { + final MonthIndex month1 = monthIndex(YearMonth.of(2021, 1), + day(LocalDate.of(2021, 1, 1), Duration.ofMinutes(10)), + day(LocalDate.of(2021, 1, 4), Duration.ofMinutes(20))); + final MonthIndex month2 = monthIndex(YearMonth.of(2021, 2), + day(LocalDate.of(2021, 2, 1), Duration.ofMinutes(5))); + simulateStorageLoadAll(month1, month2); + appService.updatePreviousMonthOvertimeField(); + + assertThat(month1.getOvertimePreviousMonth()).isZero(); + assertThat(month2.getOvertimePreviousMonth()).isEqualTo(Duration.ofMinutes(30)); + } + + private void simulateStorageLoadAll(final MonthIndex... months) + { + when(storageMock.loadAll()).thenReturn(new MultiMonthIndex(asList(months))); + } + + private DayData day(LocalDate date, Duration overtime) + { + final DayData day = modelFactory.createDayData(); + day.setDate(date); + day.setBegin(LocalTime.of(8, 0)); + day.setEnd(day.getBegin().plus(Duration.ofHours(8).plus(Duration.ofMinutes(45)).plus(overtime))); + return day; + } + + private MonthIndex monthIndex(YearMonth month, DayData... days) + { + final MonthData monthData = modelFactory.createMonthData(); + monthData.setYear(month.getYear()); + monthData.setMonth(month.getMonth()); + monthData.setDays(asList(days)); + return MonthIndex.create(contractTerms, projectServiceMock, modelFactory, monthData); + } + private DayRecord updateNow(final LocalTime now, final DayData day) { when(clockMock.getCurrentDate()).thenReturn(day.getDate()); @@ -535,4 +644,127 @@ private DayRecord updateNow(final LocalTime now, final DayData day) appService.updateNow(); return dayRecord; } + + @Test + void store() + { + final DayData day = modelFactory.createDayData(); + day.setDate(LocalDate.of(2021, 1, 5)); + final DayRecord record = new DayRecord(contractTerms, day, null, monthIndexMock, + projectServiceMock, modelFactory); + final MonthData monthData = modelFactory.createMonthData(); + monthData.setYear(2021); + monthData.setMonth(Month.JANUARY); + monthData.setDays(new ArrayList<>()); + final MonthIndex monthIndex = MonthIndex.create(contractTerms, projectServiceMock, modelFactory, + monthData); + when(storageMock.loadOrCreate(YearMonth.of(2021, 1))).thenReturn(monthIndex); + + appService.store(record); + + assertThat(monthIndex.getDay(record.getDate())).isSameAs(record); + verify(storageMock).storeMonth(same(monthIndex)); + verify(updateListenerMock).recordUpdated(same(record)); + } + + @Test + void getAvailableDataYearMonth() + { + final ArrayList list = new ArrayList<>(); + when(storageMock.getAvailableDataMonths()).thenReturn(list); + assertThat(appService.getAvailableDataYearMonth()).isSameAs(list); + } + + @Test + void getOrCreateMonth() + { + final YearMonth month = YearMonth.of(2021, 1); + when(storageMock.loadOrCreate(month)).thenReturn(monthIndexMock); + assertThat(appService.getOrCreateMonth(month)).isSameAs(monthIndexMock); + } + + @Test + void addInterruption() + { + final DelegatingAppServiceCallback appServiceCallback = new DelegatingAppServiceCallback(); + appService = createAppService(appServiceCallback, workingTimeServiceMock); + final Duration interruption = Duration.ofMinutes(10); + final LocalDate date = LocalDate.of(2021, 1, 1); + + appService.addInterruption(date, interruption); + + verify(workingTimeServiceMock).addInterruption(date, interruption); + } + + @Test + void generateProjectReport() + { + final YearMonth month = YearMonth.of(2021, 1); + final ProjectReport projectReport = mock(ProjectReport.class); + when(projectReportGeneratorMock.generateReport(month)).thenReturn(projectReport); + + assertThat(appService.generateProjectReport(month)).isSameAs(projectReport); + verify(projectReportGeneratorMock).generateReport(month); + } + + @Test + void getVacationReport() + { + final VacationReport vacationReport = mock(VacationReport.class); + when(vacationReportGeneratorMock.generateReport()).thenReturn(vacationReport); + assertThat(appService.getVacationReport()).isSameAs(vacationReport); + } + + @Test + void activities() + { + assertThat(appService.activities()).isSameAs(activityService); + } + + @Test + void projects() + { + assertThat(appService.projects()).isSameAs(projectServiceMock); + } + + @Test + void autocomplete() + { + assertThat(appService.autocomplete()).isSameAs(autocompleteServiceMock); + } + + @Test + void formatter() + { + assertThat(appService.formatter()).isSameAs(formatterServiceMock); + } + + @Test + void pluginManager() + { + assertThat(appService.pluginManager()).isSameAs(pluginManagerMock); + } + + @Test + void registerSingleInstance_otherInstanceAlreadyRunning() + { + final RunningInstanceCallback callback = mock(RunningInstanceCallback.class); + simulateOtherInstance(callback, true); + assertThat(appService.registerSingleInstance(callback)).isPresent(); + } + + private void simulateOtherInstance(final RunningInstanceCallback callback, boolean otherInstanceRunning) + { + final RegistrationResult registrationResultMock = mock(RegistrationResult.class); + when(registrationResultMock.isOtherInstanceRunning()).thenReturn(otherInstanceRunning); + when(singleInstanceService.tryToRegisterInstance(same(callback))).thenReturn(registrationResultMock); + } + + @Test + void registerSingleInstance_noInstanceAlreadyRunning() + { + final RunningInstanceCallback callback = mock(RunningInstanceCallback.class); + simulateOtherInstance(callback, false); + assertThat(appService.registerSingleInstance(callback)).isEmpty(); + } } From ad61da486f279cc261228546051e08fd972d708a Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sun, 7 Feb 2021 10:50:54 +0100 Subject: [PATCH 12/14] Add unit tests --- .../logic/service/FormatterService.java | 2 + .../logic/service/plugin/PluginManager.java | 22 ++- .../logic/service/ClockServiceTest.java | 57 +++++++ .../logic/service/FormatterServiceTest.java | 35 ++++ .../service/plugin/PluginManagerTest.java | 150 ++++++++++++++++++ .../service/plugin/PluginRegistryTest.java | 136 ++++++++++++++++ .../logic/service/plugin/TestingPlugin.java | 51 ++++++ .../org.itsallcode.whiterabbit.api.Plugin | 1 + 8 files changed, 450 insertions(+), 4 deletions(-) create mode 100644 logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ClockServiceTest.java create mode 100644 logic/src/test/java/org/itsallcode/whiterabbit/logic/service/FormatterServiceTest.java create mode 100644 logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManagerTest.java create mode 100644 logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginRegistryTest.java create mode 100644 logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/TestingPlugin.java create mode 100644 logic/src/test/resources/META-INF/services/org.itsallcode.whiterabbit.api.Plugin diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/FormatterService.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/FormatterService.java index 585f30ee..d44b8f78 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/FormatterService.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/FormatterService.java @@ -30,6 +30,7 @@ public FormatterService(Locale locale, ZoneId timeZoneId) .withLocale(locale).withZone(timeZoneId); } + @Deprecated public String format(DayRecord day) { final String dayOfWeek = day.getDate().getDayOfWeek().getDisplayName(TextStyle.SHORT_STANDALONE, locale); @@ -44,6 +45,7 @@ public String format(DayRecord day) format(day.getOverallOvertime())); } + @Deprecated private String formatDayType(DayType type) { final String formatPattern = "%1$-" + MAX_DAY_TYPE_LENGTH + "s"; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManager.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManager.java index efd2eb72..64b235f9 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManager.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManager.java @@ -49,22 +49,36 @@ public ProjectReportExporter getProjectReportExporter(String id) public Optional getMonthDataStorage() { - final List pluginIds = findPluginsSupporting(MonthDataStorage.class); + return getUniqueFeature(MonthDataStorage.class); + } + + private Optional getUniqueFeature(Class featureType) + { + final List pluginIds = findPluginsSupporting(featureType); if (pluginIds.isEmpty()) { return Optional.empty(); } if (pluginIds.size() > 1) { - throw new IllegalStateException("Found multiple plugins supporting " + MonthDataStorage.class.getName() + throw new IllegalStateException("Found multiple plugins supporting " + featureType.getName() + ": " + pluginIds + ". Please add only one storage plugin to the classpath."); } - return Optional.of(getFeature(pluginIds.get(0), MonthDataStorage.class)); + return Optional.of(getFeature(pluginIds.get(0), featureType)); } private T getFeature(String id, final Class featureType) { - return pluginRegistry.getPlugin(id).getFeature(featureType); + final PluginWrapper plugin = pluginRegistry.getPlugin(id); + if (plugin == null) + { + throw new IllegalStateException("Plugin '" + id + "' not found"); + } + if (!plugin.supports(featureType)) + { + throw new IllegalStateException("Plugin '" + id + "' does not support feature " + featureType.getName()); + } + return plugin.getFeature(featureType); } public void close() diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ClockServiceTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ClockServiceTest.java new file mode 100644 index 00000000..31ab7e96 --- /dev/null +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/ClockServiceTest.java @@ -0,0 +1,57 @@ +package org.itsallcode.whiterabbit.logic.service; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.Clock; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.YearMonth; +import java.time.ZoneId; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class ClockServiceTest +{ + private static final Instant NOW = Instant.parse("2007-12-03T10:15:30.00Z"); + private ClockService clockService; + + @BeforeEach + void setUp() + { + clockService = new ClockService( + Clock.fixed(NOW, ZoneId.of("Europe/Berlin"))); + } + + @Test + void testGetCurrentDate() + { + assertThat(clockService.getCurrentDate()).isEqualTo(LocalDate.of(2007, 12, 3)); + } + + @Test + void testGetCurrentYearMonth() + { + assertThat(clockService.getCurrentYearMonth()).isEqualTo(YearMonth.of(2007, 12)); + } + + @Test + void testGetCurrentTime() + { + assertThat(clockService.getCurrentTime()).isEqualTo(LocalTime.of(11, 15)); + } + + @Test + void testGetDurationUntilNextFullMinute() + { + assertThat(clockService.getDurationUntilNextFullMinute()).isEqualTo(Duration.ofSeconds(30)); + } + + @Test + void testInstant() + { + assertThat(clockService.instant()).isSameAs(NOW); + } +} diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/FormatterServiceTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/FormatterServiceTest.java new file mode 100644 index 00000000..cdf590bf --- /dev/null +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/FormatterServiceTest.java @@ -0,0 +1,35 @@ +package org.itsallcode.whiterabbit.logic.service; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.Duration; +import java.time.Instant; +import java.time.ZoneId; +import java.util.Locale; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class FormatterServiceTest +{ + private FormatterService formatter; + + @BeforeEach + void setUp() + { + formatter = new FormatterService(Locale.GERMAN, ZoneId.of("Europe/Berlin")); + } + + @Test + void testFormatDuration() + { + assertThat(formatter.format(Duration.ofHours(4).plusMinutes(42).plusSeconds(31))).isEqualTo("04:42"); + } + + @Test + void testFormatDateAndTime() + { + assertThat(formatter.formatDateAndTime(Instant.parse("2007-12-03T10:15:30.00Z"))) + .isEqualTo("03.12.07, 11:15:30"); + } +} diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManagerTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManagerTest.java new file mode 100644 index 00000000..1ebe32a8 --- /dev/null +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManagerTest.java @@ -0,0 +1,150 @@ +package org.itsallcode.whiterabbit.logic.service.plugin; + +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.itsallcode.whiterabbit.api.MonthDataStorage; +import org.itsallcode.whiterabbit.api.ProjectReportExporter; +import org.itsallcode.whiterabbit.logic.Config; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class PluginManagerTest +{ + @Mock + private PluginRegistry pluginRegistryMock; + + @Mock + private PluginWrapper plugin1; + @Mock + private PluginWrapper plugin2; + + private PluginManager pluginManager; + + @BeforeEach + void setUp() + { + pluginManager = new PluginManager(pluginRegistryMock); + lenient().when(plugin1.getId()).thenReturn("plugin1"); + lenient().when(plugin2.getId()).thenReturn("plugin2"); + } + + @Test + void create() + { + final Config config = mock(Config.class); + assertThat(PluginManager.create(config)).isNotNull(); + } + + @Test + void getProjectReportExporterPlugins_noPluginAvailable() + { + simulatePlugins(); + assertThat(pluginManager.getProjectReportExporterPlugins()).isEmpty(); + } + + @Test + void getProjectReportExporterPlugins_unsupportedPluginAvailable() + { + simulatePlugins(plugin1); + when(plugin1.supports(ProjectReportExporter.class)).thenReturn(false); + assertThat(pluginManager.getProjectReportExporterPlugins()).isEmpty(); + } + + @Test + void getProjectReportExporterPlugins_supportedPluginAvailable() + { + simulatePlugins(plugin1); + when(plugin1.supports(ProjectReportExporter.class)).thenReturn(true); + assertThat(pluginManager.getProjectReportExporterPlugins()).containsExactly("plugin1"); + } + + private void simulatePlugins(PluginWrapper... plugins) + { + lenient().when(pluginRegistryMock.getAllPlugins()).thenReturn(asList(plugins)); + for (final PluginWrapper plugin : plugins) + { + lenient().when(pluginRegistryMock.getPlugin(plugin.getId())).thenReturn(plugin); + } + } + + @Test + void getProjectReportExporter_noPluginAvailable_throwsException() + { + simulatePlugins(); + assertThatThrownBy(() -> pluginManager.getProjectReportExporter("unknown")) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Plugin 'unknown' not found"); + } + + @Test + void getProjectReportExporter_availableButNotSupported() + { + simulatePlugins(plugin1); + when(plugin1.supports(ProjectReportExporter.class)).thenReturn(false); + assertThatThrownBy(() -> pluginManager.getProjectReportExporter("plugin1")) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Plugin 'plugin1' does not support feature " + ProjectReportExporter.class.getName()); + } + + @Test + void getProjectReportExporter_availableAndSupported() + { + simulatePlugins(plugin1); + when(plugin1.supports(ProjectReportExporter.class)).thenReturn(true); + final ProjectReportExporter featureMock = mock(ProjectReportExporter.class); + when(plugin1.getFeature(ProjectReportExporter.class)).thenReturn(featureMock); + + assertThat(pluginManager.getProjectReportExporter("plugin1")).isNotNull().isSameAs(featureMock); + } + + @Test + void getMonthDataStorage_singleInstanceAvailable() + { + simulatePlugins(plugin1); + when(plugin1.supports(MonthDataStorage.class)).thenReturn(true); + final MonthDataStorage featureMock = mock(MonthDataStorage.class); + when(plugin1.getFeature(MonthDataStorage.class)).thenReturn(featureMock); + + assertThat(pluginManager.getMonthDataStorage()).isPresent().containsSame(featureMock); + } + + @Test + void getMonthDataStorage_noInstanceAvailable() + { + simulatePlugins(plugin1); + when(plugin1.supports(MonthDataStorage.class)).thenReturn(false); + + assertThat(pluginManager.getMonthDataStorage()).isEmpty(); + } + + @Test + void getMonthDataStorage_multipleInstancesAvailable() + { + simulatePlugins(plugin1, plugin2); + when(plugin1.supports(MonthDataStorage.class)).thenReturn(true); + when(plugin2.supports(MonthDataStorage.class)).thenReturn(true); + + assertThatThrownBy(() -> pluginManager.getMonthDataStorage()) + .isInstanceOf(IllegalStateException.class) + .hasMessage( + "Found multiple plugins supporting org.itsallcode.whiterabbit.api.MonthDataStorage: [plugin1, plugin2]. Please add only one storage plugin to the classpath."); + } + + @Test + void close() + { + pluginManager.close(); + verify(pluginRegistryMock).close(); + } + +} diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginRegistryTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginRegistryTest.java new file mode 100644 index 00000000..b6452bef --- /dev/null +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginRegistryTest.java @@ -0,0 +1,136 @@ +package org.itsallcode.whiterabbit.logic.service.plugin; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collection; + +import org.itsallcode.whiterabbit.logic.Config; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.io.TempDir; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class PluginRegistryTest +{ + @Mock + private Config configMock; + private PluginRegistry pluginRegistry; + + @BeforeEach + void setUp() + { + pluginRegistry = new PluginRegistry(configMock); + } + + @Test + void loadFromEmptyPluginDir(@TempDir Path tempDir) + { + when(configMock.getPluginDir()).thenReturn(tempDir); + pluginRegistry.load(); + assertThat(pluginRegistry.getAllPlugins()).hasSize(1); + } + + @Test + void loadFromNonExistingPluginDir() + { + when(configMock.getPluginDir()).thenReturn(Paths.get("no-such-directory")); + pluginRegistry.load(); + assertThat(pluginRegistry.getAllPlugins()).hasSize(1); + } + + @Test + void loadInvalidJar(@TempDir Path tempDir) throws IOException + { + when(configMock.getPluginDir()).thenReturn(tempDir); + Files.writeString(tempDir.resolve("invalid-plugin.jar"), ""); + pluginRegistry.load(); + assertThat(pluginRegistry.getAllPlugins()).hasSize(1); + } + + @Test + void getAllPlugins_returnsEmptyList_WhenNotLoadedYet() + { + assertThat(pluginRegistry.getAllPlugins()).isEmpty(); + } + + @Test + void getAllPlugins_returnsPlugins_WhenLoaded() + { + pluginRegistry.load(); + final Collection plugins = pluginRegistry.getAllPlugins(); + assertThat(plugins).hasSize(1); + final PluginWrapper plugin = plugins.iterator().next(); + verifyTestingPlugin(plugin); + } + + private void verifyTestingPlugin(final PluginWrapper plugin) + { + final TestingPlugin pluginInstance = plugin.getFeature(TestingPlugin.class); + assertThat(pluginInstance).isInstanceOf(TestingPlugin.class); + assertThat(pluginInstance.getId()).isEqualTo(TestingPlugin.PLUGIN_ID); + assertThat(pluginInstance.isClosed()).isFalse(); + } + + @Test + void getPlugin_failsWhenNotLoadedAndPluginNotAvailable() + { + assertThatThrownBy(() -> pluginRegistry.getPlugin("unknown")) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Plugin 'unknown' not found. Available plugins: []"); + } + + @Test + void getPlugin_failsWhenLoadedAndPluginNotAvailable() + { + pluginRegistry.load(); + assertThatThrownBy(() -> pluginRegistry.getPlugin("unknown")) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Plugin 'unknown' not found. Available plugins: [" + TestingPlugin.PLUGIN_ID + "]"); + } + + @Test + void getPlugin_returnsPluginWhenAvailable() + { + pluginRegistry.load(); + verifyTestingPlugin(pluginRegistry.getPlugin(TestingPlugin.PLUGIN_ID)); + } + + @Test + void pluginConfig_getMandatoryValue_ReturnsValue() + { + pluginRegistry.load(); + final TestingPlugin pluginInstance = pluginRegistry.getPlugin(TestingPlugin.PLUGIN_ID) + .getFeature(TestingPlugin.class); + + when(configMock.getMandatoryValue(TestingPlugin.PLUGIN_ID + ".property")).thenReturn("propertyValue"); + assertThat(pluginInstance.getConfig().getMandatoryValue("property")).isEqualTo("propertyValue"); + } + + @Test + void close_whenNoPluginLoaded() + { + assertDoesNotThrow(() -> pluginRegistry.close()); + } + + @Test + void close_closesPlugins() + { + pluginRegistry.load(); + final TestingPlugin plugin = pluginRegistry.getPlugin(TestingPlugin.PLUGIN_ID).getFeature(TestingPlugin.class); + assertThat(plugin.isClosed()).isFalse(); + + pluginRegistry.close(); + + assertThat(plugin.isClosed()).isTrue(); + } +} diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/TestingPlugin.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/TestingPlugin.java new file mode 100644 index 00000000..54e0fec1 --- /dev/null +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/TestingPlugin.java @@ -0,0 +1,51 @@ +package org.itsallcode.whiterabbit.logic.service.plugin; + +import org.itsallcode.whiterabbit.api.Plugin; +import org.itsallcode.whiterabbit.api.PluginConfiguration; + +public class TestingPlugin implements Plugin +{ + static final String PLUGIN_ID = "testingPlugin"; + private PluginConfiguration config; + private boolean closed = false; + + @Override + public void init(PluginConfiguration config) + { + this.config = config; + } + + @Override + public String getId() + { + return PLUGIN_ID; + } + + @Override + public void close() + { + this.closed = true; + } + + @Override + public boolean supports(Class featureType) + { + return TestingPlugin.class.isAssignableFrom(featureType); + } + + @Override + public T getFeature(Class featureType) + { + return featureType.cast(this); + } + + public PluginConfiguration getConfig() + { + return config; + } + + public boolean isClosed() + { + return closed; + } +} diff --git a/logic/src/test/resources/META-INF/services/org.itsallcode.whiterabbit.api.Plugin b/logic/src/test/resources/META-INF/services/org.itsallcode.whiterabbit.api.Plugin new file mode 100644 index 00000000..f5e3c6e3 --- /dev/null +++ b/logic/src/test/resources/META-INF/services/org.itsallcode.whiterabbit.api.Plugin @@ -0,0 +1 @@ +org.itsallcode.whiterabbit.logic.service.plugin.TestingPlugin From ccc88f921260d438859cf01628a856ef2c8cd6b8 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sun, 7 Feb 2021 11:48:57 +0100 Subject: [PATCH 13/14] Refactoring: add super interface for plugin features, document plugin api. --- .../whiterabbit/api/MonthDataStorage.java | 31 -------- .../itsallcode/whiterabbit/api/Plugin.java | 56 ++++++++++++++- .../whiterabbit/api/PluginConfiguration.java | 17 ++++- .../whiterabbit/api/ProgressMonitor.java | 12 ---- .../api/ProjectReportExporter.java | 8 --- .../api/features/MonthDataStorage.java | 71 +++++++++++++++++++ .../api/features/PluginFeature.java | 11 +++ .../api/features/ProgressMonitor.java | 41 +++++++++++ .../api/features/ProjectReportExporter.java | 20 ++++++ .../whiterabbit/api/model/ActivityData.java | 4 ++ .../whiterabbit/api/model/DayData.java | 4 ++ .../whiterabbit/api/model/DayType.java | 6 ++ .../whiterabbit/api/model/MonthData.java | 3 + .../whiterabbit/api/model/Project.java | 4 ++ .../whiterabbit/api/model/ProjectReport.java | 3 + .../api/model/ProjectReportActivity.java | 4 ++ .../api/model/ProjectReportDay.java | 4 ++ .../jfxui/ui/ProjectReportViewer.java | 2 +- .../jfxui/ui/widget/ProgressDialog.java | 2 +- .../logic/model/DayActivities.java | 2 +- .../whiterabbit/logic/model/DayRecord.java | 2 +- .../whiterabbit/logic/model/MonthIndex.java | 2 +- .../whiterabbit/logic/service/AppService.java | 2 +- .../logic/service/plugin/PluginManager.java | 9 +-- .../logic/service/plugin/PluginWrapper.java | 5 +- .../logic/storage/CachingStorage.java | 2 +- .../logic/storage/MonthIndexStorage.java | 2 +- .../logic/storage/data/JsonFileStorage.java | 2 +- .../logic/storage/data/JsonModelFactory.java | 2 +- .../logic/model/DayActivitiesTest.java | 2 +- .../logic/model/DayRecordTest.java | 2 +- .../logic/model/MonthIndexTest.java | 2 +- .../service/plugin/PluginManagerTest.java | 7 +- .../logic/service/plugin/TestingPlugin.java | 7 +- .../logic/storage/MonthIndexStorageTest.java | 2 +- .../storage/data/JsonFileStorageTest.java | 2 +- .../whiterabbit/plugin/demo/DemoPlugin.java | 5 +- .../demo/DemoProjectReportExporter.java | 4 +- .../plugin/pmsmart/PMSmartExportPlugin.java | 5 +- .../plugin/pmsmart/PMSmartExporter.java | 4 +- 40 files changed, 285 insertions(+), 90 deletions(-) delete mode 100644 api/src/main/java/org/itsallcode/whiterabbit/api/MonthDataStorage.java delete mode 100644 api/src/main/java/org/itsallcode/whiterabbit/api/ProgressMonitor.java delete mode 100644 api/src/main/java/org/itsallcode/whiterabbit/api/ProjectReportExporter.java create mode 100644 api/src/main/java/org/itsallcode/whiterabbit/api/features/MonthDataStorage.java create mode 100644 api/src/main/java/org/itsallcode/whiterabbit/api/features/PluginFeature.java create mode 100644 api/src/main/java/org/itsallcode/whiterabbit/api/features/ProgressMonitor.java create mode 100644 api/src/main/java/org/itsallcode/whiterabbit/api/features/ProjectReportExporter.java diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/MonthDataStorage.java b/api/src/main/java/org/itsallcode/whiterabbit/api/MonthDataStorage.java deleted file mode 100644 index 3b11db91..00000000 --- a/api/src/main/java/org/itsallcode/whiterabbit/api/MonthDataStorage.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.itsallcode.whiterabbit.api; - -import java.time.YearMonth; -import java.util.List; -import java.util.Optional; - -import org.itsallcode.whiterabbit.api.model.ActivityData; -import org.itsallcode.whiterabbit.api.model.DayData; -import org.itsallcode.whiterabbit.api.model.MonthData; - -public interface MonthDataStorage -{ - Optional load(YearMonth date); - - void store(YearMonth yearMonth, MonthData record); - - List getAvailableDataMonths(); - - List loadAll(); - - ModelFactory getModelFactory(); - - public interface ModelFactory - { - MonthData createMonthData(); - - DayData createDayData(); - - ActivityData createActivityData(); - } -} \ No newline at end of file diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/Plugin.java b/api/src/main/java/org/itsallcode/whiterabbit/api/Plugin.java index 1704a9df..4e86e64f 100644 --- a/api/src/main/java/org/itsallcode/whiterabbit/api/Plugin.java +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/Plugin.java @@ -1,14 +1,64 @@ package org.itsallcode.whiterabbit.api; +import org.itsallcode.whiterabbit.api.features.MonthDataStorage; +import org.itsallcode.whiterabbit.api.features.PluginFeature; +import org.itsallcode.whiterabbit.api.features.ProjectReportExporter; + +/** + * Implement this interface to create a plugin for WhiteRabbit. Register your + * plugin by adding file + * {@code META-INF/services/org.itsallcode.whiterabbit.api.Plugin} containing + * the full qualified class name to the jar. + * + * Available features: + *
    + *
  • {@link ProjectReportExporter}
  • + *
  • {@link MonthDataStorage}
  • + *
+ */ public interface Plugin { + /** + * Called once when loading the plugin. + * + * @param config + * the configuration of the plugin. + */ void init(PluginConfiguration config); + /** + * The ID of this plugin. IDs must be unique for all plugins. The ID is used + * as prefix for {@link PluginConfiguration#getMandatoryValue(String)}. + * + * @return the ID of this plugin. + */ String getId(); - void close(); + /** + * Check if this plugin supports the given feature. + * + * @param featureType + * the feature type. + * @return true if this plugin supports the given feature, else + * false. + */ + boolean supports(Class featureType); - boolean supports(Class featureType); + /** + * Get an instance of the given feature type. + * + * @param featureType + * the feature type. + * @param + * the type of the feature. + * @return the instance of the given feature. May return null + * or throw an exception if the feature is not supported. + */ + T getFeature(Class featureType); - T getFeature(Class featureType); + /** + * Called before closing the plugin. The plugin should cleanup any resources + * in this method. + */ + void close(); } diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/PluginConfiguration.java b/api/src/main/java/org/itsallcode/whiterabbit/api/PluginConfiguration.java index fc882823..05ba3caa 100644 --- a/api/src/main/java/org/itsallcode/whiterabbit/api/PluginConfiguration.java +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/PluginConfiguration.java @@ -1,6 +1,21 @@ package org.itsallcode.whiterabbit.api; +/** + * The configuration of a {@link Plugin} that allows retrieving configuration + * values from the WhiteRabbit properties file + * {@code ~/.whiterabbit.properties}. + */ public interface PluginConfiguration { - String getMandatoryValue(String string); + /** + * Get property {@code pluginId.propertyName} from the config file. Throws + * an exception if the property is not available. + * + * @param propertyName + * the property name to get. + * @return the value of the property. + * @throws RuntimeException + * if the property is not available in the config file. + */ + String getMandatoryValue(String propertyName); } diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/ProgressMonitor.java b/api/src/main/java/org/itsallcode/whiterabbit/api/ProgressMonitor.java deleted file mode 100644 index 9a9425e3..00000000 --- a/api/src/main/java/org/itsallcode/whiterabbit/api/ProgressMonitor.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.itsallcode.whiterabbit.api; - -public interface ProgressMonitor -{ - boolean isCanceled(); - - void beginTask(String name, int totalWork); - - void setTaskName(String name); - - void worked(int work); -} diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/ProjectReportExporter.java b/api/src/main/java/org/itsallcode/whiterabbit/api/ProjectReportExporter.java deleted file mode 100644 index e55263dc..00000000 --- a/api/src/main/java/org/itsallcode/whiterabbit/api/ProjectReportExporter.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.itsallcode.whiterabbit.api; - -import org.itsallcode.whiterabbit.api.model.ProjectReport; - -public interface ProjectReportExporter -{ - void export(ProjectReport report, ProgressMonitor progressMonitor); -} diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/features/MonthDataStorage.java b/api/src/main/java/org/itsallcode/whiterabbit/api/features/MonthDataStorage.java new file mode 100644 index 00000000..df376ae4 --- /dev/null +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/features/MonthDataStorage.java @@ -0,0 +1,71 @@ +package org.itsallcode.whiterabbit.api.features; + +import java.time.YearMonth; +import java.util.List; +import java.util.Optional; + +import org.itsallcode.whiterabbit.api.model.ActivityData; +import org.itsallcode.whiterabbit.api.model.DayData; +import org.itsallcode.whiterabbit.api.model.MonthData; + +/** + * {@link PluginFeature} that provides a storage backend for month data. This + * class may keep the data on the local disk or on a backend server. + * {@link YearMonth} is used as key for loading and storing entries. + */ +public interface MonthDataStorage extends PluginFeature +{ + /** + * @param month + * the month for which to load the data. + * @return the data for the given month. + */ + Optional load(YearMonth month); + + /** + * Store the data for a given month. + * + * @param month + * the month. + * @param data + * the data to store. + */ + void store(YearMonth month, MonthData data); + + /** + * @return all months for that data is available in the store. + */ + List getAvailableDataMonths(); + + /** + * @return all available data. + */ + List loadAll(); + + /** + * @return the model factory that can be used to create instances of the + * model. + */ + ModelFactory getModelFactory(); + + /** + * A {@link ModelFactory} allows creating new instances of the data model. + */ + public interface ModelFactory + { + /** + * @return a new {@link MonthData} instance. + */ + MonthData createMonthData(); + + /** + * @return a new {@link DayData} instance. + */ + DayData createDayData(); + + /** + * @return a new {@link ActivityData} instance. + */ + ActivityData createActivityData(); + } +} \ No newline at end of file diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/features/PluginFeature.java b/api/src/main/java/org/itsallcode/whiterabbit/api/features/PluginFeature.java new file mode 100644 index 00000000..85060dac --- /dev/null +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/features/PluginFeature.java @@ -0,0 +1,11 @@ +package org.itsallcode.whiterabbit.api.features; + +import org.itsallcode.whiterabbit.api.Plugin; + +/** + * Super interface for all features supported by a {@link Plugin}. + */ +public interface PluginFeature +{ + +} diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/features/ProgressMonitor.java b/api/src/main/java/org/itsallcode/whiterabbit/api/features/ProgressMonitor.java new file mode 100644 index 00000000..28143ab5 --- /dev/null +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/features/ProgressMonitor.java @@ -0,0 +1,41 @@ +package org.itsallcode.whiterabbit.api.features; + +/** + * A progress monitor passed to a {@link PluginFeature} that allows reporting + * the progress of process. + */ +public interface ProgressMonitor +{ + /** + * Call this method repeatedly to check, if the user wants to cancel the + * process. Abort the process if this returns true. + * + * @return true if the user has cancelled the process. + */ + boolean isCanceled(); + + /** + * Notifies that the main task is beginning. + * + * @param name + * the name of the current task shown to the user. + * @param totalWork + * the total number of work units that will be done by the task. + */ + void beginTask(String name, int totalWork); + + /** + * @param name + * the name of the current task shown to the user. + */ + void setTaskName(String name); + + /** + * Notifies that a given number of work unit of the main task has been + * completed. + * + * @param work + * the number of work units just completed. + */ + void worked(int work); +} diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/features/ProjectReportExporter.java b/api/src/main/java/org/itsallcode/whiterabbit/api/features/ProjectReportExporter.java new file mode 100644 index 00000000..b29afbae --- /dev/null +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/features/ProjectReportExporter.java @@ -0,0 +1,20 @@ +package org.itsallcode.whiterabbit.api.features; + +import org.itsallcode.whiterabbit.api.model.ProjectReport; + +/** + * A {@link PluginFeature} that allows exporting a monthly {@link ProjectReport} + * to another system. + */ +public interface ProjectReportExporter extends PluginFeature +{ + /** + * Start the export. + * + * @param report + * the report to export. + * @param progressMonitor + * a progress monitor for reporting the export progress. + */ + void export(ProjectReport report, ProgressMonitor progressMonitor); +} diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/model/ActivityData.java b/api/src/main/java/org/itsallcode/whiterabbit/api/model/ActivityData.java index 6d107153..1d477e17 100644 --- a/api/src/main/java/org/itsallcode/whiterabbit/api/model/ActivityData.java +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/model/ActivityData.java @@ -2,6 +2,10 @@ import java.time.Duration; +/** + * Model for a project activity on a given {@link DayData day} including project + * id, duration and comment. + */ public interface ActivityData { String getProjectId(); diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/model/DayData.java b/api/src/main/java/org/itsallcode/whiterabbit/api/model/DayData.java index 588615cb..1fbe72a3 100644 --- a/api/src/main/java/org/itsallcode/whiterabbit/api/model/DayData.java +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/model/DayData.java @@ -5,6 +5,10 @@ import java.time.LocalTime; import java.util.List; +/** + * Model class representing a day with date, time for begin and end of work, + * activities etc. + */ public interface DayData { LocalDate getDate(); diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/model/DayType.java b/api/src/main/java/org/itsallcode/whiterabbit/api/model/DayType.java index 323a24a8..24f9e152 100644 --- a/api/src/main/java/org/itsallcode/whiterabbit/api/model/DayType.java +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/model/DayType.java @@ -1,5 +1,8 @@ package org.itsallcode.whiterabbit.api.model; +/** + * The type of a {@link DayData day}. + */ public enum DayType { HOLIDAY(false), VACATION(false), FLEX_TIME(true), SICK(false), WORK(true), WEEKEND(false); @@ -11,6 +14,9 @@ public enum DayType this.workDay = workDay; } + /** + * @return true if you need to work on a day of this type. + */ public boolean isWorkDay() { return workDay; diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/model/MonthData.java b/api/src/main/java/org/itsallcode/whiterabbit/api/model/MonthData.java index 46a4b90b..af40d9e6 100644 --- a/api/src/main/java/org/itsallcode/whiterabbit/api/model/MonthData.java +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/model/MonthData.java @@ -4,6 +4,9 @@ import java.time.Month; import java.util.List; +/** + * Model class for data of a single month containing year, month, day data etc. + */ public interface MonthData { int getYear(); diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/model/Project.java b/api/src/main/java/org/itsallcode/whiterabbit/api/model/Project.java index 56c9d721..ae7d836e 100644 --- a/api/src/main/java/org/itsallcode/whiterabbit/api/model/Project.java +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/model/Project.java @@ -1,5 +1,9 @@ package org.itsallcode.whiterabbit.api.model; +/** + * The project you work on during an {@link ProjectReportActivity activity} + * containing an ID, label and cost carrier id. + */ public interface Project { String getProjectId(); diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/model/ProjectReport.java b/api/src/main/java/org/itsallcode/whiterabbit/api/model/ProjectReport.java index e4c4e2e5..92bebde8 100644 --- a/api/src/main/java/org/itsallcode/whiterabbit/api/model/ProjectReport.java +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/model/ProjectReport.java @@ -3,6 +3,9 @@ import java.time.YearMonth; import java.util.List; +/** + * A monthly project report. + */ public interface ProjectReport { YearMonth getMonth(); diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/model/ProjectReportActivity.java b/api/src/main/java/org/itsallcode/whiterabbit/api/model/ProjectReportActivity.java index a7ecf8cc..787d1127 100644 --- a/api/src/main/java/org/itsallcode/whiterabbit/api/model/ProjectReportActivity.java +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/model/ProjectReportActivity.java @@ -2,6 +2,10 @@ import java.time.Duration; +/** + * An activity during a {@link ProjectReportDay day} where you worked for a + * specific time duration on a {@link Project}. + */ public interface ProjectReportActivity { Project getProject(); diff --git a/api/src/main/java/org/itsallcode/whiterabbit/api/model/ProjectReportDay.java b/api/src/main/java/org/itsallcode/whiterabbit/api/model/ProjectReportDay.java index 3500d617..50dc8a60 100644 --- a/api/src/main/java/org/itsallcode/whiterabbit/api/model/ProjectReportDay.java +++ b/api/src/main/java/org/itsallcode/whiterabbit/api/model/ProjectReportDay.java @@ -3,6 +3,10 @@ import java.time.LocalDate; import java.util.List; +/** + * The projects worked on during a single day of the {@link ProjectReport} + * including date and {@link ProjectReportActivity activities}. + */ public interface ProjectReportDay { LocalDate getDate(); diff --git a/jfxui/src/main/java/org/itsallcode/whiterabbit/jfxui/ui/ProjectReportViewer.java b/jfxui/src/main/java/org/itsallcode/whiterabbit/jfxui/ui/ProjectReportViewer.java index 26cbbb8d..36d5a37c 100644 --- a/jfxui/src/main/java/org/itsallcode/whiterabbit/jfxui/ui/ProjectReportViewer.java +++ b/jfxui/src/main/java/org/itsallcode/whiterabbit/jfxui/ui/ProjectReportViewer.java @@ -8,7 +8,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.itsallcode.whiterabbit.api.ProjectReportExporter; +import org.itsallcode.whiterabbit.api.features.ProjectReportExporter; import org.itsallcode.whiterabbit.api.model.DayType; import org.itsallcode.whiterabbit.api.model.ProjectReport; import org.itsallcode.whiterabbit.api.model.ProjectReportActivity; diff --git a/jfxui/src/main/java/org/itsallcode/whiterabbit/jfxui/ui/widget/ProgressDialog.java b/jfxui/src/main/java/org/itsallcode/whiterabbit/jfxui/ui/widget/ProgressDialog.java index b054814a..b19d0d92 100644 --- a/jfxui/src/main/java/org/itsallcode/whiterabbit/jfxui/ui/widget/ProgressDialog.java +++ b/jfxui/src/main/java/org/itsallcode/whiterabbit/jfxui/ui/widget/ProgressDialog.java @@ -2,7 +2,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.itsallcode.whiterabbit.api.ProgressMonitor; +import org.itsallcode.whiterabbit.api.features.ProgressMonitor; import org.itsallcode.whiterabbit.jfxui.JavaFxUtil; import org.itsallcode.whiterabbit.jfxui.ui.UiResources; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java index 9723e2bd..29200672 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayActivities.java @@ -13,7 +13,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.itsallcode.whiterabbit.api.MonthDataStorage.ModelFactory; +import org.itsallcode.whiterabbit.api.features.MonthDataStorage.ModelFactory; import org.itsallcode.whiterabbit.api.model.ActivityData; import org.itsallcode.whiterabbit.api.model.DayData; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayRecord.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayRecord.java index f83174cf..42dbc350 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayRecord.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/DayRecord.java @@ -8,7 +8,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.itsallcode.whiterabbit.api.MonthDataStorage.ModelFactory; +import org.itsallcode.whiterabbit.api.features.MonthDataStorage.ModelFactory; import org.itsallcode.whiterabbit.api.model.DayData; import org.itsallcode.whiterabbit.api.model.DayType; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java index 4d362379..c8de5a8a 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/model/MonthIndex.java @@ -15,7 +15,7 @@ import java.util.function.Function; import java.util.stream.Stream; -import org.itsallcode.whiterabbit.api.MonthDataStorage.ModelFactory; +import org.itsallcode.whiterabbit.api.features.MonthDataStorage.ModelFactory; import org.itsallcode.whiterabbit.api.model.DayData; import org.itsallcode.whiterabbit.api.model.DayType; import org.itsallcode.whiterabbit.api.model.MonthData; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java index d764592e..147e1a32 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java @@ -16,7 +16,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.itsallcode.whiterabbit.api.MonthDataStorage; +import org.itsallcode.whiterabbit.api.features.MonthDataStorage; import org.itsallcode.whiterabbit.api.model.ProjectReport; import org.itsallcode.whiterabbit.logic.Config; import org.itsallcode.whiterabbit.logic.autocomplete.AutocompleteService; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManager.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManager.java index 64b235f9..f04f0ab6 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManager.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManager.java @@ -7,8 +7,9 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.itsallcode.whiterabbit.api.MonthDataStorage; -import org.itsallcode.whiterabbit.api.ProjectReportExporter; +import org.itsallcode.whiterabbit.api.features.MonthDataStorage; +import org.itsallcode.whiterabbit.api.features.PluginFeature; +import org.itsallcode.whiterabbit.api.features.ProjectReportExporter; import org.itsallcode.whiterabbit.logic.Config; public class PluginManager @@ -34,7 +35,7 @@ public List getProjectReportExporterPlugins() return findPluginsSupporting(ProjectReportExporter.class); } - private List findPluginsSupporting(Class featureType) + private List findPluginsSupporting(Class featureType) { return pluginRegistry.getAllPlugins().stream() .filter(plugin -> plugin.supports(featureType)) @@ -67,7 +68,7 @@ private Optional getUniqueFeature(Class feat return Optional.of(getFeature(pluginIds.get(0), featureType)); } - private T getFeature(String id, final Class featureType) + private T getFeature(String id, final Class featureType) { final PluginWrapper plugin = pluginRegistry.getPlugin(id); if (plugin == null) diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginWrapper.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginWrapper.java index 4b47d789..a1a002cb 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginWrapper.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginWrapper.java @@ -4,6 +4,7 @@ import org.itsallcode.whiterabbit.api.Plugin; import org.itsallcode.whiterabbit.api.PluginConfiguration; +import org.itsallcode.whiterabbit.api.features.PluginFeature; import org.itsallcode.whiterabbit.logic.Config; class PluginWrapper @@ -34,12 +35,12 @@ String getId() return plugin.getId(); } - boolean supports(Class featureType) + boolean supports(Class featureType) { return plugin.supports(featureType); } - T getFeature(Class featureType) + T getFeature(Class featureType) { return plugin.getFeature(featureType); } diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java index 4fca313e..61382120 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/CachingStorage.java @@ -3,7 +3,7 @@ import java.time.LocalDate; import java.util.List; -import org.itsallcode.whiterabbit.api.MonthDataStorage; +import org.itsallcode.whiterabbit.api.features.MonthDataStorage; import org.itsallcode.whiterabbit.logic.model.DayRecord; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; import org.itsallcode.whiterabbit.logic.service.project.ProjectService; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java index 4f0843df..8416517f 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorage.java @@ -11,7 +11,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.itsallcode.whiterabbit.api.MonthDataStorage; +import org.itsallcode.whiterabbit.api.features.MonthDataStorage; import org.itsallcode.whiterabbit.api.model.MonthData; import org.itsallcode.whiterabbit.logic.model.MonthIndex; import org.itsallcode.whiterabbit.logic.model.MultiMonthIndex; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java index cdbe81a9..f97dcb9f 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorage.java @@ -18,7 +18,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.itsallcode.whiterabbit.api.MonthDataStorage; +import org.itsallcode.whiterabbit.api.features.MonthDataStorage; import org.itsallcode.whiterabbit.api.model.MonthData; import org.itsallcode.whiterabbit.logic.Config; diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonModelFactory.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonModelFactory.java index be3abfac..c6418b3e 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonModelFactory.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/storage/data/JsonModelFactory.java @@ -1,6 +1,6 @@ package org.itsallcode.whiterabbit.logic.storage.data; -import org.itsallcode.whiterabbit.api.MonthDataStorage.ModelFactory; +import org.itsallcode.whiterabbit.api.features.MonthDataStorage.ModelFactory; import org.itsallcode.whiterabbit.api.model.ActivityData; import org.itsallcode.whiterabbit.api.model.DayData; import org.itsallcode.whiterabbit.api.model.MonthData; diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayActivitiesTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayActivitiesTest.java index 26cf1d9c..0181918c 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayActivitiesTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayActivitiesTest.java @@ -8,7 +8,7 @@ import java.time.Duration; import java.util.ArrayList; -import org.itsallcode.whiterabbit.api.MonthDataStorage.ModelFactory; +import org.itsallcode.whiterabbit.api.features.MonthDataStorage.ModelFactory; import org.itsallcode.whiterabbit.api.model.ActivityData; import org.itsallcode.whiterabbit.api.model.DayData; import org.itsallcode.whiterabbit.logic.service.contract.ContractTermsService; diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java index 2d1e367f..afda7931 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/DayRecordTest.java @@ -8,7 +8,7 @@ import java.time.LocalDate; import java.time.LocalTime; -import org.itsallcode.whiterabbit.api.MonthDataStorage.ModelFactory; +import org.itsallcode.whiterabbit.api.features.MonthDataStorage.ModelFactory; import org.itsallcode.whiterabbit.api.model.DayData; import org.itsallcode.whiterabbit.api.model.DayType; import org.itsallcode.whiterabbit.api.model.MonthData; diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java index 44cef575..4269f6f2 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/model/MonthIndexTest.java @@ -9,7 +9,7 @@ import java.time.Month; import java.time.YearMonth; -import org.itsallcode.whiterabbit.api.MonthDataStorage.ModelFactory; +import org.itsallcode.whiterabbit.api.features.MonthDataStorage.ModelFactory; import org.itsallcode.whiterabbit.api.model.DayData; import org.itsallcode.whiterabbit.api.model.DayType; import org.itsallcode.whiterabbit.api.model.MonthData; diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManagerTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManagerTest.java index 1ebe32a8..19a845d4 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManagerTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/PluginManagerTest.java @@ -8,8 +8,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import org.itsallcode.whiterabbit.api.MonthDataStorage; -import org.itsallcode.whiterabbit.api.ProjectReportExporter; +import org.itsallcode.whiterabbit.api.features.MonthDataStorage; +import org.itsallcode.whiterabbit.api.features.ProjectReportExporter; import org.itsallcode.whiterabbit.logic.Config; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -137,7 +137,8 @@ void getMonthDataStorage_multipleInstancesAvailable() assertThatThrownBy(() -> pluginManager.getMonthDataStorage()) .isInstanceOf(IllegalStateException.class) .hasMessage( - "Found multiple plugins supporting org.itsallcode.whiterabbit.api.MonthDataStorage: [plugin1, plugin2]. Please add only one storage plugin to the classpath."); + "Found multiple plugins supporting " + MonthDataStorage.class.getName() + + ": [plugin1, plugin2]. Please add only one storage plugin to the classpath."); } @Test diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/TestingPlugin.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/TestingPlugin.java index 54e0fec1..f73e709d 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/TestingPlugin.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/service/plugin/TestingPlugin.java @@ -2,8 +2,9 @@ import org.itsallcode.whiterabbit.api.Plugin; import org.itsallcode.whiterabbit.api.PluginConfiguration; +import org.itsallcode.whiterabbit.api.features.PluginFeature; -public class TestingPlugin implements Plugin +public class TestingPlugin implements Plugin, PluginFeature { static final String PLUGIN_ID = "testingPlugin"; private PluginConfiguration config; @@ -28,13 +29,13 @@ public void close() } @Override - public boolean supports(Class featureType) + public boolean supports(Class featureType) { return TestingPlugin.class.isAssignableFrom(featureType); } @Override - public T getFeature(Class featureType) + public T getFeature(Class featureType) { return featureType.cast(this); } diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java index 5c2f0018..cfb920a0 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/MonthIndexStorageTest.java @@ -15,7 +15,7 @@ import java.util.List; import java.util.Optional; -import org.itsallcode.whiterabbit.api.MonthDataStorage; +import org.itsallcode.whiterabbit.api.features.MonthDataStorage; import org.itsallcode.whiterabbit.api.model.MonthData; import org.itsallcode.whiterabbit.logic.model.MonthIndex; import org.itsallcode.whiterabbit.logic.model.MultiMonthIndex; diff --git a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorageTest.java b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorageTest.java index 932c1e74..bcc36a84 100644 --- a/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorageTest.java +++ b/logic/src/test/java/org/itsallcode/whiterabbit/logic/storage/data/JsonFileStorageTest.java @@ -17,7 +17,7 @@ import javax.json.bind.Jsonb; -import org.itsallcode.whiterabbit.api.MonthDataStorage.ModelFactory; +import org.itsallcode.whiterabbit.api.features.MonthDataStorage.ModelFactory; import org.itsallcode.whiterabbit.api.model.ActivityData; import org.itsallcode.whiterabbit.api.model.MonthData; import org.junit.jupiter.api.BeforeEach; diff --git a/plugins/demo/src/main/java/org/itsallcode/whiterabbit/plugin/demo/DemoPlugin.java b/plugins/demo/src/main/java/org/itsallcode/whiterabbit/plugin/demo/DemoPlugin.java index 467b7ad8..73fcfe96 100644 --- a/plugins/demo/src/main/java/org/itsallcode/whiterabbit/plugin/demo/DemoPlugin.java +++ b/plugins/demo/src/main/java/org/itsallcode/whiterabbit/plugin/demo/DemoPlugin.java @@ -2,6 +2,7 @@ import org.itsallcode.whiterabbit.api.Plugin; import org.itsallcode.whiterabbit.api.PluginConfiguration; +import org.itsallcode.whiterabbit.api.features.PluginFeature; public class DemoPlugin implements Plugin { @@ -24,13 +25,13 @@ public void close() } @Override - public boolean supports(Class featureType) + public boolean supports(Class featureType) { return featureType.isAssignableFrom(DemoProjectReportExporter.class); } @Override - public T getFeature(Class featureType) + public T getFeature(Class featureType) { if (featureType.isAssignableFrom(DemoProjectReportExporter.class)) { diff --git a/plugins/demo/src/main/java/org/itsallcode/whiterabbit/plugin/demo/DemoProjectReportExporter.java b/plugins/demo/src/main/java/org/itsallcode/whiterabbit/plugin/demo/DemoProjectReportExporter.java index f0099073..c3d22113 100644 --- a/plugins/demo/src/main/java/org/itsallcode/whiterabbit/plugin/demo/DemoProjectReportExporter.java +++ b/plugins/demo/src/main/java/org/itsallcode/whiterabbit/plugin/demo/DemoProjectReportExporter.java @@ -2,8 +2,8 @@ import java.time.Duration; -import org.itsallcode.whiterabbit.api.ProgressMonitor; -import org.itsallcode.whiterabbit.api.ProjectReportExporter; +import org.itsallcode.whiterabbit.api.features.ProgressMonitor; +import org.itsallcode.whiterabbit.api.features.ProjectReportExporter; import org.itsallcode.whiterabbit.api.model.ProjectReport; import org.itsallcode.whiterabbit.api.model.ProjectReportActivity; import org.itsallcode.whiterabbit.api.model.ProjectReportDay; diff --git a/plugins/pmsmart/src/main/java/org/itsallcode/whiterabbit/plugin/pmsmart/PMSmartExportPlugin.java b/plugins/pmsmart/src/main/java/org/itsallcode/whiterabbit/plugin/pmsmart/PMSmartExportPlugin.java index a36fa781..563d661a 100644 --- a/plugins/pmsmart/src/main/java/org/itsallcode/whiterabbit/plugin/pmsmart/PMSmartExportPlugin.java +++ b/plugins/pmsmart/src/main/java/org/itsallcode/whiterabbit/plugin/pmsmart/PMSmartExportPlugin.java @@ -2,6 +2,7 @@ import org.itsallcode.whiterabbit.api.Plugin; import org.itsallcode.whiterabbit.api.PluginConfiguration; +import org.itsallcode.whiterabbit.api.features.PluginFeature; import org.itsallcode.whiterabbit.plugin.pmsmart.web.WebDriverFactory; public class PMSmartExportPlugin implements Plugin @@ -15,13 +16,13 @@ public void init(PluginConfiguration config) } @Override - public boolean supports(Class featureType) + public boolean supports(Class featureType) { return featureType.isAssignableFrom(PMSmartExporter.class); } @Override - public T getFeature(Class featureType) + public T getFeature(Class featureType) { if (featureType.isAssignableFrom(PMSmartExporter.class)) { diff --git a/plugins/pmsmart/src/main/java/org/itsallcode/whiterabbit/plugin/pmsmart/PMSmartExporter.java b/plugins/pmsmart/src/main/java/org/itsallcode/whiterabbit/plugin/pmsmart/PMSmartExporter.java index 38a7508b..eb11e7ed 100644 --- a/plugins/pmsmart/src/main/java/org/itsallcode/whiterabbit/plugin/pmsmart/PMSmartExporter.java +++ b/plugins/pmsmart/src/main/java/org/itsallcode/whiterabbit/plugin/pmsmart/PMSmartExporter.java @@ -3,8 +3,8 @@ import java.util.Map; import org.itsallcode.whiterabbit.api.PluginConfiguration; -import org.itsallcode.whiterabbit.api.ProgressMonitor; -import org.itsallcode.whiterabbit.api.ProjectReportExporter; +import org.itsallcode.whiterabbit.api.features.ProgressMonitor; +import org.itsallcode.whiterabbit.api.features.ProjectReportExporter; import org.itsallcode.whiterabbit.api.model.ProjectReport; import org.itsallcode.whiterabbit.api.model.ProjectReportActivity; import org.itsallcode.whiterabbit.api.model.ProjectReportDay; From e32e4707ff557ccfb4546de26331e825c91a8509 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sun, 7 Feb 2021 11:59:42 +0100 Subject: [PATCH 14/14] Fix sonar warnings --- .../itsallcode/whiterabbit/logic/service/AppService.java | 3 +++ .../itsallcode/whiterabbit/logic/service/DayReporter.java | 3 +++ .../whiterabbit/logic/service/FormatterService.java | 6 ++++++ 3 files changed, 12 insertions(+) diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java index 147e1a32..da70bcc1 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/AppService.java @@ -169,6 +169,9 @@ public SchedulingService scheduler() return this.schedulingService; } + /** + * @deprecated will be removed in the next version. + */ @Deprecated public void report() { diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/DayReporter.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/DayReporter.java index c2acf880..ce8f63bc 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/DayReporter.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/DayReporter.java @@ -6,6 +6,9 @@ import org.apache.logging.log4j.Logger; import org.itsallcode.whiterabbit.logic.model.DayRecord; +/** + * @deprecated will be removed in the next version. + */ @Deprecated public class DayReporter { diff --git a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/FormatterService.java b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/FormatterService.java index d44b8f78..358c443d 100644 --- a/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/FormatterService.java +++ b/logic/src/main/java/org/itsallcode/whiterabbit/logic/service/FormatterService.java @@ -30,6 +30,9 @@ public FormatterService(Locale locale, ZoneId timeZoneId) .withLocale(locale).withZone(timeZoneId); } + /** + * @deprecated will be removed in the next version. + */ @Deprecated public String format(DayRecord day) { @@ -45,6 +48,9 @@ public String format(DayRecord day) format(day.getOverallOvertime())); } + /** + * @deprecated will be removed in the next version. + */ @Deprecated private String formatDayType(DayType type) {