====== Crawler ======
Le crawler est un module supplémentaire fournit par la librairie qui permet de télécharger une série à partir d'un site web. Ceci permet la lecture "on the go" de séries sans la nécessité de posséder une connexion internet.
Le fonctionnement et la structure du crawler est une ré-implémentation du projet [[https://github.com/ltouroumov/MangaArchive|MangaArchive]] qui a inspiré la création de cette application.
hide empty fields
hide empty methods
class CrawlerFactory {
+ register(crawler)
+ registerAll()
+ forUrl(url): Optional
+ getExecutor(): Executor
+ setExecutor(executor)
}
CrawlerFactory ..> ICrawler : provides
interface ICrawler {
+ canCrawl(url): boolean
+ crawl(url): WebSeries
+ crawlAsync(url): ProgressFuture
}
ICrawler .> WebSeries : creates
class Builder {
+ build(webSeries): boolean
+ buildAsync(webSries): ProgressFuture
}
WebSeries .> Builder
WebSeries --> WebVolume
WebVolume --> WebChapter
WebChapter --> WebPage
Le module fonctionne en deux temps: Crawling et Building.
La phase de crawling construit un //descripteur// à partir des informations disponibles sur la page de la série. Un descripteur contient les métadonnées de la série construite en "best effort" et la référence vers toutes les images (pages) nécessaires à la construction de la série. Les images sont organisées en //chapitres// eux mêmes organisés en //volumes//. L'inclusion des chapitres dans la structure permet à certaines implémentations de mieux gérer la récupération des URLs des pages.
Une fois la création du descripteur complet il est possible de le sauvegarder au format JSON pour une utilisation future, par exemple si le processus de construiction est interrompu.
La phase de building utilise le //descripteur// créé lors de la phase précédente, effectue le téléchargement de toutes les images et les ajoute à un nouveau volume qui est alors ajouté à la série. Une fois le processus terminé, le série est ajoutée à la racine du catalogue et peut être modifiée par l'utilisateur.
Chacun des deux modules fournit deux modes de fonctionnement: Synchrone et Asynchrone. Le mode synchrone fontionne en appelant le mode Asynchrone et en bloquant sur le résultat. Le mode asynchrone détache son fonctionnement en arrière-plan dans l'executor fournit par la CrawlerFactory et retourne un ProgressFuture. L'objet ProgressFuture hérite de CompletableFuture et permet en plus de reporter l'avancement de la tâche aux objets s'étant enregistrés pour recevoir les notifications de progrès.
===== Gestion de Progression =====
La gestion de la progression se fait au travers d'une classe héritant de ''CompletableFuture''. Les [[https://en.wikipedia.org/wiki/Futures_and_promises|Promesses et Futures]] sont déjà fortement utilisées dans d'autre parties de l'application ou les opérations asynchrones sont nécessaires, par exemple, lors du chargement d'un volume. Dans le cas courant, en plus de fournir la promesse d'une réponse, étant donné que l'opération peut durer plusieurs minutes, elle doit aussi fournir à son appelant un moyen de surveiller l'avancement de l'opération. Une option aurait été de créer une classe spécialisée pour cette tâche, mais cela aurait nécessité à l'appelant de devoir gérer un objet supplémentaire. L'option choisie à été de créer une classe ''ProgressFuture'' qui dérive de ''CompletableFuture'' et qui fournit la possibilité à la tâche de communiquer son avancement à travers un canal asynchrone à son appelant.
hide empty fields
hide empty methods
class CompletableFuture {
+ whenComplete(consumer)
+ whenCompleteAsync(consumer, executor)
}
CompletableFuture <|-- ProgressFuture
class ProgressFuture {
+ whenProgress(consumer)
+ whenProgressAsync(consumer, executor)
+ whenMessage(consumer)
+ whenMessageAsync(consumer, executor)
}