<commit_before>package com.bookbase.app.model.repository;

import com.bookbase.app.database.AppDatabase;
import com.bookbase.app.library.addBook.AddBookActivity;
import com.bookbase.app.mainscreen.HomeScreen;
import com.bookbase.app.model.dao.AuthorDao;
import com.bookbase.app.model.dao.BookDao;
import com.bookbase.app.model.dao.GenreDao;
import com.bookbase.app.model.entity.Author;
import com.bookbase.app.model.entity.Book;
import com.bookbase.app.model.entity.Genre;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Repository {

    private static Repository repository;
    private BookDao bookDao;
    private AuthorDao authorDao;
    private GenreDao genreDao;

    private List<Book> books;
    private List<Author> authors;
    private List<Genre> genres;
    private Map<Integer, String> authorMap;
    private Map<Integer, String> genreMap;

    private Repository(){
        AppDatabase db = AppDatabase.getDatabase(HomeScreen.getContext());
        bookDao = db.bookDao();
        authorDao = db.authorDao();
        genreDao = db.genreDao();

        books = bookDao.getBooks();
        authors = authorDao.getAuthors();
        genres = genreDao.getGenres();
        authorMap = new HashMap<>();
        genreMap = new HashMap<>();

        refreshGenreMap();
        refreshAuthorMap();
    }

    public static Repository getRepository(){
        if(repository == null){
            repository = new Repository();
        }
        return  repository;
    }

    public boolean addNewBook(Book book, Author author, Genre genre, AddBookActivity.AddBookCallback callback){
        /*
        * OFFLOAD ALL OF THIS TO ANOTHER THREAD.
        * 1. Call callback.inProgress() to start loading spinner in UI.
        * 2. Insert Author and Genre, get id's back.
        * 3. Set author and genre fields of book.
        * 4. Insert book.
        * 5. Call either onSuccess() or onFailure() callback methods depending on outcome.
        * */
        return true;
    }

    // Book methods.
    public Book getBook(int bookId) {
        // TODO: Off load to background thread.
        return bookDao.getSingleBook(bookId);
    }

    public List<Book> getBookList() {
        // TODO: Off load to background thread.
        if(books.isEmpty() || books == null){
            books = bookDao.getBooks();
        }
        return books;
    }

    public int updateBook(Book book) {
        // TODO: Off load to background thread.
        return bookDao.update(book);
    }

    public int deleteBook(Book book) {
        // TODO: Off load to background thread.
        return bookDao.deleteBook(book);
    }

    // Author Methods.
    public String getAuthorName(int authorId){
        String name = authorMap.get(authorId);
        return name != null ? name : "No Author Name";
    }

    // Genre Methods.
    public String getGenreName(int genreId){
        String name = genreMap.get(genreId);
        return name != null ? name : "No Genre Name";
    }

    // Refresh methods.
    private void refreshBooks(){
        // TODO: Off load to background thread.
        if(books != null){
            bookDao.getBooks();
        }
    }<commit_msg>WIP implementing Repository class<commit_after>package com.bookbase.app.model.repository;

import com.bookbase.app.database.AppDatabase;
import com.bookbase.app.library.addBook.AddBookActivity;
import com.bookbase.app.mainscreen.HomeScreen;
import com.bookbase.app.model.dao.AuthorDao;
import com.bookbase.app.model.dao.BookDao;
import com.bookbase.app.model.dao.GenreDao;
import com.bookbase.app.model.entity.Author;
import com.bookbase.app.model.entity.Book;
import com.bookbase.app.model.entity.Genre;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Repository {

    // Thread pool parameters.
    private static int NUM_CORES = Runtime.getRuntime().availableProcessors();
    private static final int KEEP_ALIVE_TIME = 1;
    private static final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;
    private final BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
    private ThreadPoolExecutor pool;

    private static Repository repository;
    private BookDao bookDao;
    private AuthorDao authorDao;
    private GenreDao genreDao;

    private List<Book> books;
    private List<Author> authors;
    private List<Genre> genres;
    private Map<Integer, String> authorMap;
    private Map<Integer, String> genreMap;

    private static final int IDLE = 0;
    private static final int AUTHOR_INSERTED = 1;
    private static final int GENRE_INSERTED = 2;
    private static final int BOOK_INSERTED = 3;
    private static int insertState = IDLE;
    private static Author insertedAuthor;
    private static Genre insertedGenre;

    private Repository(){
        pool = new ThreadPoolExecutor(
                NUM_CORES,
                NUM_CORES,
                KEEP_ALIVE_TIME,
                KEEP_ALIVE_TIME_UNIT,
                workQueue);

        AppDatabase db = AppDatabase.getDatabase(HomeScreen.getContext());
        bookDao = db.bookDao();
        authorDao = db.authorDao();
        genreDao = db.genreDao();

        books = bookDao.getBooks();
        authors = authorDao.getAuthors();
        genres = genreDao.getGenres();
        authorMap = new HashMap<>();
        genreMap = new HashMap<>();

        refreshGenreMap();
        refreshAuthorMap();
    }

    public static Repository getRepository(){
        if(repository == null){
            repository = new Repository();
        }
        return  repository;
    }

    public void addNewBook(Book book, AddBookActivity.AddBookCallback callback){

        callback.inProgress();
        while(insertState != BOOK_INSERTED){
            switch(insertState){
                case IDLE:
                    insertAuthor(book.getAuthor());
                    break;
                case AUTHOR_INSERTED:
                    insertGenre(book.getGenre());
                    book.setAuthor(insertedAuthor);
                    break;
                case GENRE_INSERTED:
                    book.setGenre(insertedGenre);
                    insertBook(book);
                    break;
                case BOOK_INSERTED:
                    callback.onSuccess();
                default:
                    callback.onFailure();
                    throw new IllegalStateException("Invalid insertState: " + insertState);
            }

        }
        if(insertState == BOOK_INSERTED){
            callback.onSuccess();
        }
    }

    // Book methods.
    public Book getBook(int bookId) {
        // TODO: Off load to background thread.
        return bookDao.getSingleBook(bookId);
    }

    public List<Book> getBookList() {
        // TODO: Off load to background thread.
        if(books.isEmpty() || books == null){
            books = bookDao.getBooks();
        }
        return books;
    }

    private void insertBook(final Book book){
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                bookDao.insert(book);
                insertState = BOOK_INSERTED;
            }
        };
        pool.execute(runnable);
    }

    public int updateBook(Book book) {
        // TODO: Off load to background thread.
        return bookDao.update(book);
    }

    public int deleteBook(Book book) {
        // TODO: Off load to background thread.
        return bookDao.deleteBook(book);
    }

    // Author Methods.
    public String getAuthorName(int authorId){
        String name = authorMap.get(authorId);
        return name != null ? name : "No Author Name";
    }

    public void insertAuthor(final Author author){
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                authorDao.insert(author);
                insertState = AUTHOR_INSERTED;
                insertedAuthor = author;
            }
        };
        pool.execute(runnable);
    }

    // Genre Methods.
    public String getGenreName(int genreId){
        String name = genreMap.get(genreId);
        return name != null ? name : "No Genre Name";
    }

    public void insertGenre(final Genre genre){
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                genreDao.insert(genre);
                insertState = GENRE_INSERTED;
                insertedGenre = genre;
            }
        };
        pool.execute(runnable);
    }

    // Refresh methods.
    private void refreshBooks(){
        // TODO: Off load to background thread.
        if(books != null){
            bookDao.getBooks();
        }
    }
{'fraction_non_alphanumeric': 0.0941678840319137, 'fraction_numerical': 0.001123721766490617, 'mean_word_length': 2.167259786476868, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5831953', 'n_tokens_mistral': 2481, 'n_tokens_neox': 2434, 'n_words': 625}