From 250d7b443c0a3648fc8cfc11872aef186ecd9d93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Mazur?= Date: Sun, 14 Jul 2024 11:34:04 +0200 Subject: [PATCH] Refactoring of model to be mroe generic --- .gitignore | 3 ++ .../db/{PocketItem.java => Item.java} | 9 +++- ...{PocketItemMapper.java => ItemMapper.java} | 9 ++-- ...temRepository.java => ItemRepository.java} | 4 +- .../{pocket/api => db}/ItemStatus.java | 2 +- .../eu/cybershu/pocketstats/db/Source.java | 13 ++++++ .../pocketstats/pocket/PocketApiService.java | 24 +++++----- .../PocketResponseItemsDeserializer.java | 9 +++- .../pocketstats/pocket/api/ListItem.java | 2 +- .../pocket/api/PocketItemStatsService.java | 11 ++--- .../pocket/api/PocketItemStatus.java | 32 ++++++++++++++ .../stats/StatsWithStatusType.java | 2 +- src/main/raporting/raport.ipynb | 6 +-- .../cybershu/pocketstats/ItemBuilder.groovy | 44 +++++++++++++++++++ .../pocketstats/PocketItemBuilder.groovy | 43 ------------------ .../pocket/api/PocketGetResponseTest.groovy | 2 + ....groovy => ItemStatsServiceIntTest.groovy} | 22 +++++----- 17 files changed, 153 insertions(+), 84 deletions(-) rename src/main/java/eu/cybershu/pocketstats/db/{PocketItem.java => Item.java} (86%) rename src/main/java/eu/cybershu/pocketstats/db/{PocketItemMapper.java => ItemMapper.java} (65%) rename src/main/java/eu/cybershu/pocketstats/db/{PocketItemRepository.java => ItemRepository.java} (59%) rename src/main/java/eu/cybershu/pocketstats/{pocket/api => db}/ItemStatus.java (87%) create mode 100644 src/main/java/eu/cybershu/pocketstats/db/Source.java create mode 100644 src/main/java/eu/cybershu/pocketstats/pocket/api/PocketItemStatus.java create mode 100644 src/test/groovy/eu/cybershu/pocketstats/ItemBuilder.groovy delete mode 100644 src/test/groovy/eu/cybershu/pocketstats/PocketItemBuilder.groovy rename src/test/groovy/eu/cybershu/pocketstats/pocket/stats/{PocketItemStatsServiceIntTest.groovy => ItemStatsServiceIntTest.groovy} (96%) diff --git a/.gitignore b/.gitignore index 0dd648f..8372704 100644 --- a/.gitignore +++ b/.gitignore @@ -175,3 +175,6 @@ src/.DS_Store src/main/.DS_Store src/main/raporting/.DS_Store !/.env + +.bin/ +node_modules \ No newline at end of file diff --git a/src/main/java/eu/cybershu/pocketstats/db/PocketItem.java b/src/main/java/eu/cybershu/pocketstats/db/Item.java similarity index 86% rename from src/main/java/eu/cybershu/pocketstats/db/PocketItem.java rename to src/main/java/eu/cybershu/pocketstats/db/Item.java index ad7a2ba..47aa674 100644 --- a/src/main/java/eu/cybershu/pocketstats/db/PocketItem.java +++ b/src/main/java/eu/cybershu/pocketstats/db/Item.java @@ -1,7 +1,6 @@ package eu.cybershu.pocketstats.db; import eu.cybershu.pocketstats.pocket.api.DomainMetadata; -import eu.cybershu.pocketstats.pocket.api.ItemStatus; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @@ -14,7 +13,7 @@ @Data @NoArgsConstructor @EqualsAndHashCode(of = {"id", "url", "title", "status", "timeAdded", "timeRead"}) -public class PocketItem { +public class Item { @Id private String id; private String url; @@ -33,4 +32,10 @@ public class PocketItem { private String lang; private DomainMetadata domainMetadata; private List tags; + + /** + * article, email, document... + **/ + private String category; // todo as a enum + private Source source; } diff --git a/src/main/java/eu/cybershu/pocketstats/db/PocketItemMapper.java b/src/main/java/eu/cybershu/pocketstats/db/ItemMapper.java similarity index 65% rename from src/main/java/eu/cybershu/pocketstats/db/PocketItemMapper.java rename to src/main/java/eu/cybershu/pocketstats/db/ItemMapper.java index 3059fe1..34b87e3 100644 --- a/src/main/java/eu/cybershu/pocketstats/db/PocketItemMapper.java +++ b/src/main/java/eu/cybershu/pocketstats/db/ItemMapper.java @@ -3,6 +3,7 @@ import eu.cybershu.pocketstats.pocket.api.ListItem; import eu.cybershu.pocketstats.pocket.api.Tag; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import java.util.Collections; @@ -10,13 +11,15 @@ import java.util.Map; @Mapper(componentModel = "spring") -public interface PocketItemMapper { - PocketItemMapper INSTANCE = Mappers.getMapper(PocketItemMapper.class); +public interface ItemMapper { + ItemMapper INSTANCE = Mappers.getMapper(ItemMapper.class); static List mapTags(Map tags) { if (tags == null || tags.isEmpty()) return Collections.emptyList(); else return tags.keySet().stream().toList(); } - PocketItem apiToEntity(ListItem item); + @Mapping(target = "category", constant = "article") + @Mapping(target = "source", constant = "POCKET") + Item apiToEntity(ListItem item); } diff --git a/src/main/java/eu/cybershu/pocketstats/db/PocketItemRepository.java b/src/main/java/eu/cybershu/pocketstats/db/ItemRepository.java similarity index 59% rename from src/main/java/eu/cybershu/pocketstats/db/PocketItemRepository.java rename to src/main/java/eu/cybershu/pocketstats/db/ItemRepository.java index a3617ca..067e501 100644 --- a/src/main/java/eu/cybershu/pocketstats/db/PocketItemRepository.java +++ b/src/main/java/eu/cybershu/pocketstats/db/ItemRepository.java @@ -6,6 +6,6 @@ import java.util.Optional; @Service -public interface PocketItemRepository extends MongoRepository { - Optional findById(String id); +public interface ItemRepository extends MongoRepository { + Optional findById(String id); } diff --git a/src/main/java/eu/cybershu/pocketstats/pocket/api/ItemStatus.java b/src/main/java/eu/cybershu/pocketstats/db/ItemStatus.java similarity index 87% rename from src/main/java/eu/cybershu/pocketstats/pocket/api/ItemStatus.java rename to src/main/java/eu/cybershu/pocketstats/db/ItemStatus.java index be938f9..b4a0166 100644 --- a/src/main/java/eu/cybershu/pocketstats/pocket/api/ItemStatus.java +++ b/src/main/java/eu/cybershu/pocketstats/db/ItemStatus.java @@ -1,4 +1,4 @@ -package eu.cybershu.pocketstats.pocket.api; +package eu.cybershu.pocketstats.db; import com.fasterxml.jackson.annotation.JsonValue; diff --git a/src/main/java/eu/cybershu/pocketstats/db/Source.java b/src/main/java/eu/cybershu/pocketstats/db/Source.java new file mode 100644 index 0000000..bf3debf --- /dev/null +++ b/src/main/java/eu/cybershu/pocketstats/db/Source.java @@ -0,0 +1,13 @@ +package eu.cybershu.pocketstats.db; + +public enum Source { + POCKET("pocket"), + INSTAPAPER("instapaper"), + READER("reader"); + + private final String sourceType; + + Source(String sourceType) { + this.sourceType = sourceType; + } +} diff --git a/src/main/java/eu/cybershu/pocketstats/pocket/PocketApiService.java b/src/main/java/eu/cybershu/pocketstats/pocket/PocketApiService.java index d5033f2..4a4ebb1 100644 --- a/src/main/java/eu/cybershu/pocketstats/pocket/PocketApiService.java +++ b/src/main/java/eu/cybershu/pocketstats/pocket/PocketApiService.java @@ -27,10 +27,10 @@ public class PocketApiService { private final HttpClient client; private final ObjectMapper mapper; - private final PocketItemRepository pocketItemRepository; + private final ItemRepository itemRepository; private final MigrationStatusRepository migrationStatusRepository; private final PocketAuthorizationService authorizationService; - private final PocketItemMapper pocketItemMapper; + private final ItemMapper itemMapper; private final EventsPublisher eventsPublisher; @@ -39,7 +39,7 @@ public class PocketApiService { @Value("${auth.pocket.url.get}") private String pocketGetUrl; - public PocketApiService(PocketItemRepository pocketItemRepository, + public PocketApiService(ItemRepository itemRepository, MigrationStatusRepository migrationStatusRepository, PocketAuthorizationService authorizationService, EventsPublisher eventsPublisher) { this.migrationStatusRepository = migrationStatusRepository; @@ -51,8 +51,8 @@ public PocketApiService(PocketItemRepository pocketItemRepository, .connectTimeout(Duration.ofSeconds(20)) .build(); this.mapper = new ObjectMapper(); - this.pocketItemMapper = PocketItemMapper.INSTANCE; - this.pocketItemRepository = pocketItemRepository; + this.itemMapper = ItemMapper.INSTANCE; + this.itemRepository = itemRepository; } public SyncStatus importFromSinceLastUpdate() throws IOException, InterruptedException { @@ -88,19 +88,19 @@ public Integer importAllToDbSince(Instant sinceWhen) throws IOException, Interru .items() .values() .stream() - .map(pocketItemMapper::apiToEntity) + .map(itemMapper::apiToEntity) .toList(); - List pocketItems = pocketItemRepository.saveAll(models); + List items = itemRepository.saveAll(models); MigrationStatus migrationStatus = new MigrationStatus(); migrationStatus.id(UUID.randomUUID() .toString()); migrationStatus.date(Instant.now()); - migrationStatus.migratedItems(pocketItems.size()); + migrationStatus.migratedItems(items.size()); migrationStatusRepository.save(migrationStatus); - return pocketItems.size(); + return items.size(); } public int importAll() throws IOException, InterruptedException { @@ -110,7 +110,7 @@ public int importAll() throws IOException, InterruptedException { final var count = 300; int gotItems = 0; - List importedItems = new LinkedList<>(); + List importedItems = new LinkedList<>(); while (true) { log.debug("offset:{}, count:{}", offset, count); @@ -131,13 +131,13 @@ public int importAll() throws IOException, InterruptedException { var models = pocketResponse.items() .values() .stream() - .map(pocketItemMapper::apiToEntity) + .map(itemMapper::apiToEntity) .toList(); importedItems.addAll(models); gotItems += items.size(); - pocketItemRepository.saveAll(importedItems); + itemRepository.saveAll(importedItems); offset += count; } diff --git a/src/main/java/eu/cybershu/pocketstats/pocket/PocketResponseItemsDeserializer.java b/src/main/java/eu/cybershu/pocketstats/pocket/PocketResponseItemsDeserializer.java index 0aca3e4..bd4a155 100644 --- a/src/main/java/eu/cybershu/pocketstats/pocket/PocketResponseItemsDeserializer.java +++ b/src/main/java/eu/cybershu/pocketstats/pocket/PocketResponseItemsDeserializer.java @@ -9,12 +9,14 @@ import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import eu.cybershu.pocketstats.pocket.api.ListItem; +import lombok.extern.slf4j.Slf4j; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; +@Slf4j public class PocketResponseItemsDeserializer extends JsonDeserializer> { @Override public Map deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { @@ -27,7 +29,12 @@ public Map deserialize(JsonParser p, DeserializationContext ct if (node.isObject()) { TypeReference> typeRef = new TypeReference<>() { }; - return codec.readValue(node.traverse(), typeRef); + try { + return codec.readValue(node.traverse(), typeRef); + } catch (NoSuchFieldError e) { + log.error("Error deserializing field", e); + throw e; + } } else { throw new IllegalArgumentException("Expected items as object. Got " + node); } diff --git a/src/main/java/eu/cybershu/pocketstats/pocket/api/ListItem.java b/src/main/java/eu/cybershu/pocketstats/pocket/api/ListItem.java index 7b5e11f..41caa9a 100644 --- a/src/main/java/eu/cybershu/pocketstats/pocket/api/ListItem.java +++ b/src/main/java/eu/cybershu/pocketstats/pocket/api/ListItem.java @@ -15,7 +15,7 @@ public record ListItem(@JsonProperty("item_id") String id, @JsonProperty("resolved_id") String resolvedId, @JsonProperty("given_url") String url, @JsonProperty("given_title") String title, @JsonDeserialize(converter = StringBooleanToBoolean.class) @JsonProperty("favorite") Boolean favorite, - @JsonProperty("status") ItemStatus status, + @JsonProperty("status") PocketItemStatus status, @JsonProperty("time_added") @JsonDeserialize(converter = LongToInstantConverter.class) Instant timeAdded, @JsonProperty("time_updated") @JsonDeserialize(converter = LongToInstantConverter.class) Instant timeUpdated, @JsonDeserialize(converter = LongToInstantConverter.class) @JsonProperty("time_read") Instant timeRead, diff --git a/src/main/java/eu/cybershu/pocketstats/pocket/api/PocketItemStatsService.java b/src/main/java/eu/cybershu/pocketstats/pocket/api/PocketItemStatsService.java index 007df3a..73197cb 100644 --- a/src/main/java/eu/cybershu/pocketstats/pocket/api/PocketItemStatsService.java +++ b/src/main/java/eu/cybershu/pocketstats/pocket/api/PocketItemStatsService.java @@ -2,6 +2,7 @@ import com.mongodb.client.AggregateIterable; import com.mongodb.client.MongoCollection; +import eu.cybershu.pocketstats.db.ItemStatus; import eu.cybershu.pocketstats.events.UserSynchronizedItemsEvent; import eu.cybershu.pocketstats.stats.DayStat; import eu.cybershu.pocketstats.stats.DayStatsRecords; @@ -244,16 +245,16 @@ public PeriodItemsStats itemsStatsTotal() { .append("count", new Document("$sum", 1L))))); - Map itemStats = new HashMap<>(); + Map itemStats = new HashMap<>(); for (Document docs : result) { String name = docs.getString("_id"); long count = docs.getLong("count"); - itemStats.put(ItemStatus.valueOf(name), count); + itemStats.put(PocketItemStatus.valueOf(name), count); } return new PeriodItemsStats( - itemStats.get(ItemStatus.TO_READ) + itemStats.get(ItemStatus.ARCHIVED), - itemStats.get(ItemStatus.ARCHIVED)); + itemStats.get(PocketItemStatus.TO_READ) + itemStats.get(PocketItemStatus.ARCHIVED), + itemStats.get(PocketItemStatus.ARCHIVED)); } private MongoCollection getPocketItemsCollection() { @@ -313,7 +314,7 @@ public ActivityHeatmapStats heatmapOfStatus(StatsWithStatusType type) { match = new Document("$match", new Document("status", new Document("$exists", true) - .append("$ne", ItemStatus.DELETED))); + .append("$ne", PocketItemStatus.DELETED))); } else { match = new Document("$match", new Document("status", itemStatus.name())); diff --git a/src/main/java/eu/cybershu/pocketstats/pocket/api/PocketItemStatus.java b/src/main/java/eu/cybershu/pocketstats/pocket/api/PocketItemStatus.java new file mode 100644 index 0000000..65c9043 --- /dev/null +++ b/src/main/java/eu/cybershu/pocketstats/pocket/api/PocketItemStatus.java @@ -0,0 +1,32 @@ +package eu.cybershu.pocketstats.pocket.api; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +public enum PocketItemStatus { + TO_READ(0), + ARCHIVED(1), + DELETED(2); + + private final int status; + + PocketItemStatus(int status) { + this.status = status; + } + + @JsonValue + public int getStatus() { + return status; + } + + @JsonCreator + public static PocketItemStatus forValue(int status) { + for (PocketItemStatus itemStatus : PocketItemStatus.values()) { + if (itemStatus.getStatus() == status) { + return itemStatus; + } + } + + throw new IllegalArgumentException("Unknown status: " + status); + } +} diff --git a/src/main/java/eu/cybershu/pocketstats/stats/StatsWithStatusType.java b/src/main/java/eu/cybershu/pocketstats/stats/StatsWithStatusType.java index e6927a1..3b3b4bf 100644 --- a/src/main/java/eu/cybershu/pocketstats/stats/StatsWithStatusType.java +++ b/src/main/java/eu/cybershu/pocketstats/stats/StatsWithStatusType.java @@ -1,6 +1,6 @@ package eu.cybershu.pocketstats.stats; -import eu.cybershu.pocketstats.pocket.api.ItemStatus; +import eu.cybershu.pocketstats.db.ItemStatus; public enum StatsWithStatusType { ARCHIVED, diff --git a/src/main/raporting/raport.ipynb b/src/main/raporting/raport.ipynb index 311e43a..b5f2cd2 100644 --- a/src/main/raporting/raport.ipynb +++ b/src/main/raporting/raport.ipynb @@ -9,7 +9,7 @@ "outputs": [ { "data": { - "text/plain": "{'_id': '285932937',\n 'url': 'http://www.expertsacademy.com/3-casestudy',\n 'title': 'Brendon Burchard presents Experts Academy - Millionaire Training for The Ne',\n 'favorite': False,\n 'status': 'ARCHIVED',\n 'timeAdded': datetime.datetime(2013, 2, 10, 11, 55, 4),\n 'timeUpdated': datetime.datetime(2013, 3, 31, 14, 10, 47),\n 'timeRead': datetime.datetime(2013, 3, 31, 14, 10, 45),\n 'resolvedTitle': '',\n 'resolvedUrl': 'http://www.expertsacademy.com/3-casestudy',\n 'excerpt': '',\n 'wordCount': 0,\n 'lang': '',\n 'tags': [],\n '_class': 'eu.cybershu.pocketstats.db.PocketItem'}" + "text/plain": "{'_id': '285932937',\n 'url': 'http://www.expertsacademy.com/3-casestudy',\n 'title': 'Brendon Burchard presents Experts Academy - Millionaire Training for The Ne',\n 'favorite': False,\n 'status': 'ARCHIVED',\n 'timeAdded': datetime.datetime(2013, 2, 10, 11, 55, 4),\n 'timeUpdated': datetime.datetime(2013, 3, 31, 14, 10, 47),\n 'timeRead': datetime.datetime(2013, 3, 31, 14, 10, 45),\n 'resolvedTitle': '',\n 'resolvedUrl': 'http://www.expertsacademy.com/3-casestudy',\n 'excerpt': '',\n 'wordCount': 0,\n 'lang': '',\n 'tags': [],\n '_class': 'eu.cybershu.pocketstats.db.Item'}" }, "execution_count": 1, "metadata": {}, @@ -35,8 +35,8 @@ "outputs": [ { "data": { - "text/plain": " _id url \\\n0 285932937 http://www.expertsacademy.com/3-casestudy \n1 39977635 http://www.bookbuzzr.com/blog/book-marketing/1... \n2 44514414 http://www.smashingmagazine.com/2010/08/14/25-... \n3 128936829 http://www.expertsacademy.com/1-10essentials \n4 351833833 http://www.programfiles.pl/program-2125-ZenWri... \n\n title favorite status \\\n0 Brendon Burchard presents Experts Academy - Mi... False ARCHIVED \n1 12 Ways to Market Your Book By Giving Away Fre... False ARCHIVED \n2 25 Useful Videos and Presentations for Designe... False ARCHIVED \n3 Brendon Burchard presents Experts Academy - Mi... False ARCHIVED \n4 ZenWriter 1.0 • pobierz program za darmo • dow... False ARCHIVED \n\n timeAdded timeUpdated timeRead \\\n0 2013-02-10 11:55:04 2013-03-31 14:10:47 2013-03-31 14:10:45 \n1 2013-06-08 23:14:47 2014-02-28 20:30:07 2014-02-28 20:30:02 \n2 2012-12-20 18:14:44 2013-05-17 15:40:01 2013-05-17 15:40:01 \n3 2013-01-18 09:45:11 2013-03-31 14:04:23 2013-03-31 14:04:21 \n4 2013-05-07 10:18:49 2013-05-17 15:19:48 2013-05-17 15:19:48 \n\n resolvedTitle \\\n0 \n1 12 Ways to Market Your Book By Giving Away Fre... \n2 25 Useful Videos and Presentations for Designe... \n3 \n4 Opis programu ZenWriter 1.0: \n\n resolvedUrl \\\n0 http://www.expertsacademy.com/3-casestudy \n1 http://www.bookbuzzr.com/blog/book-marketing/1... \n2 http://www.smashingmagazine.com/2010/08/14/25-... \n3 http://www.expertsacademy.com/1-10essentials \n4 http://www.programfiles.pl/program-2125-ZenWri... \n\n excerpt wordCount lang tags \\\n0 0.0 [] \n1 The idea of permission marketing can be extend... 598.0 [] \n2 With the huge number of design-related confere... 1220.0 en [] \n3 0.0 en [] \n4 ZenWriter 1.0 - edytor tekstu dla Windows, któ... 183.0 [] \n\n _class \\\n0 eu.cybershu.pocketstats.db.PocketItem \n1 eu.cybershu.pocketstats.db.PocketItem \n2 eu.cybershu.pocketstats.db.PocketItem \n3 eu.cybershu.pocketstats.db.PocketItem \n4 eu.cybershu.pocketstats.db.PocketItem \n\n domainMetadata timeFavorited \n0 NaN NaT \n1 NaN NaT \n2 {'name': 'Smashing Magazine', 'logo': 'https:/... NaT \n3 NaN NaT \n4 NaN NaT ", - "text/html": "
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
_idurltitlefavoritestatustimeAddedtimeUpdatedtimeReadresolvedTitleresolvedUrlexcerptwordCountlangtags_classdomainMetadatatimeFavorited
0285932937http://www.expertsacademy.com/3-casestudyBrendon Burchard presents Experts Academy - Mi...FalseARCHIVED2013-02-10 11:55:042013-03-31 14:10:472013-03-31 14:10:45http://www.expertsacademy.com/3-casestudy0.0[]eu.cybershu.pocketstats.db.PocketItemNaNNaT
139977635http://www.bookbuzzr.com/blog/book-marketing/1...12 Ways to Market Your Book By Giving Away Fre...FalseARCHIVED2013-06-08 23:14:472014-02-28 20:30:072014-02-28 20:30:0212 Ways to Market Your Book By Giving Away Fre...http://www.bookbuzzr.com/blog/book-marketing/1...The idea of permission marketing can be extend...598.0[]eu.cybershu.pocketstats.db.PocketItemNaNNaT
244514414http://www.smashingmagazine.com/2010/08/14/25-...25 Useful Videos and Presentations for Designe...FalseARCHIVED2012-12-20 18:14:442013-05-17 15:40:012013-05-17 15:40:0125 Useful Videos and Presentations for Designe...http://www.smashingmagazine.com/2010/08/14/25-...With the huge number of design-related confere...1220.0en[]eu.cybershu.pocketstats.db.PocketItem{'name': 'Smashing Magazine', 'logo': 'https:/...NaT
3128936829http://www.expertsacademy.com/1-10essentialsBrendon Burchard presents Experts Academy - Mi...FalseARCHIVED2013-01-18 09:45:112013-03-31 14:04:232013-03-31 14:04:21http://www.expertsacademy.com/1-10essentials0.0en[]eu.cybershu.pocketstats.db.PocketItemNaNNaT
4351833833http://www.programfiles.pl/program-2125-ZenWri...ZenWriter 1.0 • pobierz program za darmo • dow...FalseARCHIVED2013-05-07 10:18:492013-05-17 15:19:482013-05-17 15:19:48Opis programu ZenWriter 1.0:http://www.programfiles.pl/program-2125-ZenWri...ZenWriter 1.0 - edytor tekstu dla Windows, któ...183.0[]eu.cybershu.pocketstats.db.PocketItemNaNNaT
\n
" + "text/plain": " _id url \\\n0 285932937 http://www.expertsacademy.com/3-casestudy \n1 39977635 http://www.bookbuzzr.com/blog/book-marketing/1... \n2 44514414 http://www.smashingmagazine.com/2010/08/14/25-... \n3 128936829 http://www.expertsacademy.com/1-10essentials \n4 351833833 http://www.programfiles.pl/program-2125-ZenWri... \n\n title favorite status \\\n0 Brendon Burchard presents Experts Academy - Mi... False ARCHIVED \n1 12 Ways to Market Your Book By Giving Away Fre... False ARCHIVED \n2 25 Useful Videos and Presentations for Designe... False ARCHIVED \n3 Brendon Burchard presents Experts Academy - Mi... False ARCHIVED \n4 ZenWriter 1.0 • pobierz program za darmo • dow... False ARCHIVED \n\n timeAdded timeUpdated timeRead \\\n0 2013-02-10 11:55:04 2013-03-31 14:10:47 2013-03-31 14:10:45 \n1 2013-06-08 23:14:47 2014-02-28 20:30:07 2014-02-28 20:30:02 \n2 2012-12-20 18:14:44 2013-05-17 15:40:01 2013-05-17 15:40:01 \n3 2013-01-18 09:45:11 2013-03-31 14:04:23 2013-03-31 14:04:21 \n4 2013-05-07 10:18:49 2013-05-17 15:19:48 2013-05-17 15:19:48 \n\n resolvedTitle \\\n0 \n1 12 Ways to Market Your Book By Giving Away Fre... \n2 25 Useful Videos and Presentations for Designe... \n3 \n4 Opis programu ZenWriter 1.0: \n\n resolvedUrl \\\n0 http://www.expertsacademy.com/3-casestudy \n1 http://www.bookbuzzr.com/blog/book-marketing/1... \n2 http://www.smashingmagazine.com/2010/08/14/25-... \n3 http://www.expertsacademy.com/1-10essentials \n4 http://www.programfiles.pl/program-2125-ZenWri... \n\n excerpt wordCount lang tags \\\n0 0.0 [] \n1 The idea of permission marketing can be extend... 598.0 [] \n2 With the huge number of design-related confere... 1220.0 en [] \n3 0.0 en [] \n4 ZenWriter 1.0 - edytor tekstu dla Windows, któ... 183.0 [] \n\n _class \\\n0 eu.cybershu.pocketstats.db.Item \n1 eu.cybershu.pocketstats.db.Item \n2 eu.cybershu.pocketstats.db.Item \n3 eu.cybershu.pocketstats.db.Item \n4 eu.cybershu.pocketstats.db.Item \n\n domainMetadata timeFavorited \n0 NaN NaT \n1 NaN NaT \n2 {'name': 'Smashing Magazine', 'logo': 'https:/... NaT \n3 NaN NaT \n4 NaN NaT ", + "text/html": "
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
_idurltitlefavoritestatustimeAddedtimeUpdatedtimeReadresolvedTitleresolvedUrlexcerptwordCountlangtags_classdomainMetadatatimeFavorited
0285932937http://www.expertsacademy.com/3-casestudyBrendon Burchard presents Experts Academy - Mi...FalseARCHIVED2013-02-10 11:55:042013-03-31 14:10:472013-03-31 14:10:45http://www.expertsacademy.com/3-casestudy0.0[]eu.cybershu.pocketstats.db.ItemNaNNaT
139977635http://www.bookbuzzr.com/blog/book-marketing/1...12 Ways to Market Your Book By Giving Away Fre...FalseARCHIVED2013-06-08 23:14:472014-02-28 20:30:072014-02-28 20:30:0212 Ways to Market Your Book By Giving Away Fre...http://www.bookbuzzr.com/blog/book-marketing/1...The idea of permission marketing can be extend...598.0[]eu.cybershu.pocketstats.db.ItemNaNNaT
244514414http://www.smashingmagazine.com/2010/08/14/25-...25 Useful Videos and Presentations for Designe...FalseARCHIVED2012-12-20 18:14:442013-05-17 15:40:012013-05-17 15:40:0125 Useful Videos and Presentations for Designe...http://www.smashingmagazine.com/2010/08/14/25-...With the huge number of design-related confere...1220.0en[]eu.cybershu.pocketstats.db.Item{'name': 'Smashing Magazine', 'logo': 'https:/...NaT
3128936829http://www.expertsacademy.com/1-10essentialsBrendon Burchard presents Experts Academy - Mi...FalseARCHIVED2013-01-18 09:45:112013-03-31 14:04:232013-03-31 14:04:21http://www.expertsacademy.com/1-10essentials0.0en[]eu.cybershu.pocketstats.db.ItemNaNNaT
4351833833http://www.programfiles.pl/program-2125-ZenWri...ZenWriter 1.0 • pobierz program za darmo • dow...FalseARCHIVED2013-05-07 10:18:492013-05-17 15:19:482013-05-17 15:19:48Opis programu ZenWriter 1.0:http://www.programfiles.pl/program-2125-ZenWri...ZenWriter 1.0 - edytor tekstu dla Windows, któ...183.0[]eu.cybershu.pocketstats.db.ItemNaNNaT
\n
" }, "execution_count": 2, "metadata": {}, diff --git a/src/test/groovy/eu/cybershu/pocketstats/ItemBuilder.groovy b/src/test/groovy/eu/cybershu/pocketstats/ItemBuilder.groovy new file mode 100644 index 0000000..c7ee4c7 --- /dev/null +++ b/src/test/groovy/eu/cybershu/pocketstats/ItemBuilder.groovy @@ -0,0 +1,44 @@ +package eu.cybershu.pocketstats + + +import eu.cybershu.pocketstats.db.Item +import eu.cybershu.pocketstats.db.ItemStatus + +import java.time.Instant + +class ItemBuilder { + static Item todo(Instant timeAdded = Instant.now(), + String title = "Johhny Doe eats banana", String url = "http://localhost/url/") { + def item = new Item() + item.status(ItemStatus.TO_READ) + item.timeAdded(timeAdded) + + item.id(UUID.randomUUID().toString()) + item.url(url) + item.title(title) + item.excerpt(title.md5()) + + item + } + + static Item archived(Instant timeAdded = Instant.now(), + Instant timeRead = Instant.now(), + String title = "Johhny Doe eated banana", String url = "http://localhost/url/") { + def item = new Item() + item.status(ItemStatus.ARCHIVED) + item.timeAdded(timeAdded) + item.timeRead(timeRead) + item.timeUpdated(timeRead) + item.id(UUID.randomUUID().toString()) + item.url(url) + item.title(title) + item.excerpt(title.md5()) + + item + } + + static Item withLang(Item item, String lang) { + item.lang(lang) + item + } +} diff --git a/src/test/groovy/eu/cybershu/pocketstats/PocketItemBuilder.groovy b/src/test/groovy/eu/cybershu/pocketstats/PocketItemBuilder.groovy deleted file mode 100644 index 7c128eb..0000000 --- a/src/test/groovy/eu/cybershu/pocketstats/PocketItemBuilder.groovy +++ /dev/null @@ -1,43 +0,0 @@ -package eu.cybershu.pocketstats - -import eu.cybershu.pocketstats.db.PocketItem -import eu.cybershu.pocketstats.pocket.api.ItemStatus - -import java.time.Instant - -class PocketItemBuilder { - static PocketItem todo(Instant timeAdded = Instant.now(), - String title = "Johhny Doe eats banana", String url = "http://localhost/url/") { - def item = new PocketItem() - item.status(ItemStatus.TO_READ) - item.timeAdded(timeAdded) - - item.id(UUID.randomUUID().toString()) - item.url(url) - item.title(title) - item.excerpt(title.md5()) - - item - } - - static PocketItem archived(Instant timeAdded = Instant.now(), - Instant timeRead = Instant.now(), - String title = "Johhny Doe eated banana", String url = "http://localhost/url/") { - def item = new PocketItem() - item.status(ItemStatus.ARCHIVED) - item.timeAdded(timeAdded) - item.timeRead(timeRead) - item.timeUpdated(timeRead) - item.id(UUID.randomUUID().toString()) - item.url(url) - item.title(title) - item.excerpt(title.md5()) - - item - } - - static PocketItem withLang(PocketItem item, String lang) { - item.lang(lang) - item - } -} diff --git a/src/test/groovy/eu/cybershu/pocketstats/pocket/api/PocketGetResponseTest.groovy b/src/test/groovy/eu/cybershu/pocketstats/pocket/api/PocketGetResponseTest.groovy index 25a055a..e1103e0 100644 --- a/src/test/groovy/eu/cybershu/pocketstats/pocket/api/PocketGetResponseTest.groovy +++ b/src/test/groovy/eu/cybershu/pocketstats/pocket/api/PocketGetResponseTest.groovy @@ -91,6 +91,8 @@ class PocketGetResponseTest extends BaseTest { item.timeAdded() item.timeRead() + item.status() == PocketItemStatus.TO_READ + item.timeFavorited() item.favorite() diff --git a/src/test/groovy/eu/cybershu/pocketstats/pocket/stats/PocketItemStatsServiceIntTest.groovy b/src/test/groovy/eu/cybershu/pocketstats/pocket/stats/ItemStatsServiceIntTest.groovy similarity index 96% rename from src/test/groovy/eu/cybershu/pocketstats/pocket/stats/PocketItemStatsServiceIntTest.groovy rename to src/test/groovy/eu/cybershu/pocketstats/pocket/stats/ItemStatsServiceIntTest.groovy index 7b0ad22..5d49cc4 100644 --- a/src/test/groovy/eu/cybershu/pocketstats/pocket/stats/PocketItemStatsServiceIntTest.groovy +++ b/src/test/groovy/eu/cybershu/pocketstats/pocket/stats/ItemStatsServiceIntTest.groovy @@ -1,7 +1,8 @@ package eu.cybershu.pocketstats.pocket.stats -import eu.cybershu.pocketstats.db.PocketItem -import eu.cybershu.pocketstats.db.PocketItemRepository + +import eu.cybershu.pocketstats.db.Item +import eu.cybershu.pocketstats.db.ItemRepository import eu.cybershu.pocketstats.pocket.api.BaseTest import eu.cybershu.pocketstats.pocket.api.ItemsStatsAggregated import eu.cybershu.pocketstats.pocket.api.PocketItemStatsService @@ -20,7 +21,7 @@ import spock.lang.Shared import java.time.* import java.time.temporal.ChronoUnit -import static eu.cybershu.pocketstats.PocketItemBuilder.* +import static eu.cybershu.pocketstats.ItemBuilder.* import static org.assertj.core.api.Assertions.assertThat @TestConfiguration @@ -34,9 +35,9 @@ class TestConfig { @SpringBootTest @ContextConfiguration(classes = TestConfig.class) @AutoConfigureDataMongo -class PocketItemStatsServiceIntTest extends BaseTest { +class ItemStatsServiceIntTest extends BaseTest { @Autowired - private PocketItemRepository repository + private ItemRepository repository @Autowired private PocketItemStatsService statsService @@ -90,7 +91,8 @@ class PocketItemStatsServiceIntTest extends BaseTest { archived(now, TimeUtils.instantTodayEnd()), ]) - assert repository.saveAll(items).size() == items.size() + def saved = repository.saveAll(items) + assert saved.size() == items.size() def start = LocalDate.now(clock).minusDays(7) def end = LocalDate.now(clock) @@ -371,13 +373,13 @@ class PocketItemStatsServiceIntTest extends BaseTest { assertThat(stats.added()).isEqualTo(expectedAdded) } - private PocketItem hourAndDayArchivedItem(int hour, int weekday) { + private Item hourAndDayArchivedItem(int hour, int weekday) { def date = instantWithHourAndWeekday(hour, weekday) archived(date, date) } - private PocketItem hourAndDayAddedItem(int hour, int weekday) { + private Item hourAndDayAddedItem(int hour, int weekday) { def date = instantWithHourAndWeekday(hour, weekday) todo(date) } @@ -391,7 +393,7 @@ class PocketItemStatsServiceIntTest extends BaseTest { modifiedDateTime.atZone(ZoneId.systemDefault()).toInstant() } - private PocketItem daysDiffAdded(int days) { + private Item daysDiffAdded(int days) { def timeAdded = instantDaysDiffers(days) String title = "read " + timeAdded String url = "http://local/random" @@ -399,7 +401,7 @@ class PocketItemStatsServiceIntTest extends BaseTest { todo(timeAdded, title, url) } - private PocketItem daysDiffArchived(int days, Instant dayAdded) { + private Item daysDiffArchived(int days, Instant dayAdded) { def timeAdded = instantDaysDiffers(days) String title = "read " + timeAdded String url = "http://local/random"