PROJECT: Bibliotek

This portfolio page showcases my contributions to Bibliotek.

Overview

Bibliotek is a free book cataloguing application that is simple, fast, and easy to use. It is targeted at heavy readers who require a hassle-free way of managing and keep tracking of their read and unread books.

Summary of contributions

  • Major enhancement: Added a command to search for books in National Library Board (NLB) catalogue

    • What it does: Allows the user to easily check for the availability of books in NLB libraries.

    • Justification: The user may wish to check if a book is available in the library before deciding whether to read it, or may just want a convenient way of searching for books in the library.

    • Highlights: This function paves the way to extensions beyond NLB libraries and to customized automated book availability checking; functionalities which make Bibliotek more unique.

  • Minor enhancement: Added the ability to view recently selected books

    • What it does: Allows the user to view his recently selected books.

    • Justification: The user may have recently selected a book in one of his/her searches, and regret not adding that book into his/her book shelf. With this function, he/she can easily locate that book without having to perform the searches again.

  • Code contributed: [Functional code] [Test code]

  • Other contributions:

    • Project management:

      • Maintained the issue tracker on Github.

    • Enhancements to existing features:

      • Morphed Address Book 4 into Bibliotek (Pull requests #56, #57, #72)

      • Refactored code (Pull requests #116, #156, #169)

      • Made individual commands handle undo themselves (Pull request #170)

      • Added command autocorrection (Pull request #171)

    • Documentation:

    • Community:

      • PRs reviewed: (Pull requests #58, #62, #91, #134)

      • Reported bugs and suggestions for other teams in the class (issues #76, #80, #83, #87)

Contributions to the User Guide

Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users.

Finding a book in the library : library (since v1.5)

If you want to check whether a book is available in the library, use library.
Format: library INDEX

  • Checks for the availability of the book at INDEX in a pre-configured library.

  • Default library searched is National Library Board.

You can only perform library with Internet connection.

Suppose you have the following books in your display list.

LibraryCommandBefore

If you want to search the library for Harry Potter and the Classical World, enter library 3.

Bibliotek shows Searching for the book in the library…​ to indicate that your library command is being processed. This may take some time since data is being loaded from the online library catalogue.

LibraryCommandSearching

Once the data is ready, Bibliotek shows Showing availability of book: TITLE - Authors: AUTHORS. The availability of the book in the library will show up in the right panel shortly after, as shown below.

You can only interact with (e.g. scroll) the right panel when loading is fully completed.
In the event that loading isn’t completed after a long time, you should try the command again.
LibraryCommandAfter
If Bibliotek shows Failed to retrieve information from online., it means your search request has timed out. You should try again after some time.

Listing recently viewed books : recent (since v1.2)

You recently selected a book in one of your searches but did not add it into your book shelf, and now you have trouble searching up that book again? No worries, recent is designed to take care of this.
Format: recent

  • Lists the books you recently selected in reverse chronological order.

  • Limited to the last 50 books.

You can select books in the recent list, but this will not count as a newest selection.

Suppose you recently selected The Ivory Tower and Harry Potter in your search results.

SelectCommand

You did not add the book into your book shelf. After performing various other selections, you regret not adding The Ivory Tower and Harry Potter into your book shelf. Instead of performing the search again, you can enter recent to view recently selected books.

Bibliotek shows Listed xx recently selected books. to indicate that your recent command is successful. You can scroll down the left panel to locate The Ivory Tower and Harry Potter (index 7 in this case).

RecentCommand

You can then enter add 7 to add the book into your book shelf.

If you don’t see the intended book in the list, then too many book selections have been performed after that book.

Contributions to the Developer Guide

Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project.

Check for availability of book in NLB library

The library command allows the user to easily check for the availability of books in NLB libraries. This eliminates the need to manually enter search information into the NLB catalogue. The user can use this information to decide when or whether to read a book.

Current implementation

When a library command is entered, a LibraryCommand will be created if the parsing of the command was successful, which will make a call to searchLibraryForBook(Book) on the Network API. This will result in an asynchronous HTTP request being made to NLB Catalogue. Once the HTTP request completes, the operations in the .thenApply(…​), shown in the code block below, will execute.

    private CompletableFuture<String> execute(String url, Book book) {
        return httpClient
                .makeGetRequest(url)
                .thenApply(NlbCatalogueApi::requireHtmlContentType)
                .thenApply(NlbCatalogueApi::requireHttpStatusOk)
                .thenApply(HttpResponse::getResponseBody)
                .thenApply(result -> NlbResultHelper.getUrl(result, book));
    }

This is summarized by the following activity diagram:

LibraryCommandActivityDiagram

The CompletableFuture completes exceptionally if the content type or status code is wrong. Else, a URL of the page showing availability of the target book, if any, is obtained. This depends on the response HTML, which can be categorized into the following:

  • Full display (the page we want): The URL which the HTTP GET request was made to is returned.

  • Non-empty list of results: The URL of the top result is returned.

  • Empty list of results: A custom message, reporting that no result is found, is returned.

Once the necessary result is obtained, the following method in LibraryCommand is executed:

    private void onSuccessfulRequest(String result, Book book) {
        EventsCenter.getInstance().post(new ShowLibraryResultRequestEvent(result));
        EventsCenter.getInstance().post(new NewResultAvailableEvent(String.format(MESSAGE_SUCCESS, book)));
    }

ShowLibraryResultRequestEvent is handled by MainWindow and BookInLibraryPanel to load the URL using a WebView and display the webpage. The loaded page is post-processed using a script to show only the relevant section.

Design considerations

Aspect: How to show availability of the book
  • Alternative 1 (current choice): Load the webpage using a WebView.

    • Pros: Immune to changes in structure of that webpage.

    • Cons: Lesser flexibility in structure and content. Also subject to limitations of WebView.

  • Alternative 2: Extract the relevant information from the HTTP response and design a new panel to show the results.

    • Pros: Greater control over structure and content.

    • Cons: Vulnerable to changes in structure of that webpage.

  • Alternative 1 (current choice): Perform basic search, which uses a HTTP GET request.

    • Pros: Faster response time.

    • Cons: Searched keyword seems to be matched to title or authors only.

  • Alternative 2: Perform advanced search, which uses a HTTP POST request.

    • Pros: Able to limit the search results using more parameters such as publication year or ISBN.

    • Cons: Slower response time.

Aspect: Whether to load in WebView directly or pre-process through Network component
  • Alternative 1 (current choice): Pre-process HTTP response in Network component, then send intended URL to WebView.

    • Pros: Processing happens behind the scene, and does not distract the user.

    • Cons: User is subject to waiting times without feedback on progress. Furthermore, the control flow becomes more complicated since a URL still needs to be passed to and loaded on the WebView eventually.

  • Alternative 2: Load search URL in WebView and navigate to intended page using script.

    • Pros: Easier to implement. Eliminate the need to modify Network component.

    • Cons: User will be able to see the navigation between pages.

View recently selected books

The recent command allows the user to view books that he/she recently selected. This allows the user to easily look back for a particular book, and to add it into his/her book shelf without having to perform a search again.

Current implementation

Recently selected books are stored in a UniqueBookCircularList which resides in ModelManager. Model exposes a method addRecentBook(Book) to add new book selections. Whenever a new book is selected, LogicManager handles the BookListSelectionChangedEvent and adds the book into the list using addRecentBook(Book).

When recent is entered, it will be parsed into a RecentCommand, which when executed, sets the ActiveListType to RECENT_BOOKS. It then posts ActiveListChangedEvent to the EventCenter to signal this change. The interaction between components is shown in the diagram below.

SequenceDiagramRecentCommandLogic
ActiveListType is needed because the commands that users can perform on different lists differ. For example, users cannot delete books if the ActiveListType is RECENT_BOOKS.

ActiveListChangedEvent is handled by MainWindow, which updates the list displayed in BookListPanel.

SequenceDiagramRecentCommandEvent

UniqueBookCircularList has size 50 by default. For illustration purposes, assume we have a UniqueBookCircularList of size 2 that is empty at the start. ActiveListType is BOOK_SHELF.

The user performs select 1 to view information on the 1st book in the book shelf. The selected book is added onto the UniqueBookCircularList.

RecentCommandListOne
If select fails to execute (eg. given index is invalid), the list will remain unchanged.

The user then selects another book with select 2. The book is added to the front of the UniqueBookCircularList.

RecentCommandListTwo
Selecting a book directly from the UI (without using select command) will also update the list according.

Now if the user performs select 1 again, the book One, which already exists in the list, will be removed from the list and added again so that it is in the first index of the list (most recently selected).

RecentCommandListThree

Note that the UniqueBookCircularList is currently full. When user performs select 3, since Three is not in the list, the book at the last index (the least recent selection) is removed to make space for Three (Two in this case).

RecentCommandListFour
UniqueBookCircularList::equals is order sensitive since the order determines the recency.

When Bibliotek is exited, the data in the UniqueBookCircularList is stored in the format of BookShelf. This data is read and converted to UniqueBookCircularList upon opening Bibliotek.

Design considerations

Aspect: Type of selected books that are shown
  • Alternative 1 (current choice): All books selected from the user’s book shelf or search results.

    • Pros: More intuitive for the user.

    • Cons: Users can easily find books in his book shelf. Including these books in recent list may not be useful and take up space.

  • Alternative 2: Only books selected from the user’s search results.

    • Pros: Users are more likely to need recent to find these books. We can reduce clutter by only showing these books.

    • Cons: Less intuitive for the user. We also need to deal with books that are added or deleted after selection.

Aspect: Data structure to hold the recently selected books data
  • Alternative 1 (current choice): Make a new type of book list UniqueBookCircularList.

    • Pros: Can make the size limit and add mechanism a property of the new list.

    • Cons: Have to deal with multiple data structures to hold data for different purposes.

  • Alternative 2: Use BookShelf.

    • Pros: Re-use of existing data structure.

    • Cons: BookShelf supports functionalities that are not needed to store recently selected books.