SearchProvider.cs

175 lines | 5.239 kB Blame History Raw Download
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.IO;

using Microsoft.EntityFrameworkCore;

using Tools.PdfProvider;

using Calibre.Model.Database;
using Calibre.Model.Database.Entities;

using Calibre.Model.Domain.Entities;

using LibraryText.Entities;

namespace Calibre.Model.Domain.Dal
{
    public class SearchProvider
    {
        private readonly SimplePdfReader SimplePdfReader;


        public SearchProvider(
            SimplePdfReader simplePdfReader
            )
        {
            SimplePdfReader = simplePdfReader;
        }


        public async Task<Dictionary<Library, BookWithLibraryContainer[]>> GetBooksByLibrariesAsync(            
            Func<Book, bool> whereExpression = null,
            bool includeTags = true,
            bool includeAutors = true,
            bool includeFileData = true,
            bool includeLang = true,
            params Library[] libraries
            )
        {
            List<CalibreContext> contexts
                = new List<CalibreContext>(libraries.Length);

            Dictionary<Library, Task<Book[]>> data
                = new Dictionary<Library, Task<Book[]>>(libraries.Length);

            try
            {
                foreach (var elem in libraries)
                {
                    var connectionString = Library.BuildConnectionStringFromPath(elem.DbFile.FullName);

                    var context = new CalibreContext(connectionString)
                    {
                        AsNoTracking = false,
                        //LibraryDirectory = libraryDirectory
                    };
                    contexts.Add(context);

                    IQueryable<Book> selectExpr = context
                        .Books;

                    //1) Подгружаем теги
                    if (includeTags)
                    {
                        selectExpr = selectExpr
                            .Include(e => e.Tags)
                            .ThenInclude(e => e.TagItem);
                    }

                    //2) Подгружаем авторов
                    if (includeAutors)
                    {
                        selectExpr = selectExpr
                            .Include(e => e.Autors)
                            .ThenInclude(e => e.AuthorItem);
                    }

                    //3) Подгружаем данные о фалах
                    if (includeFileData)
                    {
                        selectExpr = selectExpr
                            .Include(e => e.FileData);
                    }

                    if (includeLang)
                    {
                        selectExpr = selectExpr
                            .Include(e => e.Languages)
                            .ThenInclude(e => e.LangItem);
                    }

                    //4) Условие поиска
                    if (whereExpression != null)
                    {
                        selectExpr = selectExpr
                            .Where(whereExpression)
                            .AsQueryable();
                    }

                    var selectResultTask = selectExpr.ToArrayAsync();
                    data.Add(elem, selectResultTask);
                }

                await Task.WhenAll(
                    data.Values.ToArray()
                    );
            }
            finally
            {
                contexts.ForEach(
                    e => e.Dispose()
                    );
            }


            Dictionary<Library, BookWithLibraryContainer[]> result 
                = new Dictionary<Library, BookWithLibraryContainer[]>(libraries.Length);
            foreach (var elem in data)
            {
                var library = elem.Key;
                var libraryProxy = new ImmutableProxy<Library>(library);

                var libBooks = elem.Value.Result;

                var books = libBooks
                    .Select(
                        e2 => BookWithLibraryContainer.Create(e2, libraryProxy)
                        )
                    .ToArray();

                result.Add(library, books);
            }

            return result;
        }

        public async Task<Dictionary<BookWithLibraryContainer, string>> GetTextByBooksAsync(
            IList<BookWithLibraryContainer> books,
            bool ignoreError,
            Func<BookWithLibraryContainer, string, bool> whereExpression = null
            )
        {
            Dictionary<BookWithLibraryContainer, string> result 
                = new Dictionary<BookWithLibraryContainer, string>(books.Count);

            foreach (var elem in books)
            {
                var bookText = await elem.ReadFileAsync(
                    async (s) => 
                    {
                        var res = await SimplePdfReader.ReadPdfAsync(s, ignoreError);
                        return res;
                    }
                    );

                if (whereExpression != null)
                {
                    if (!whereExpression(elem, bookText)) 
                    {
                        continue;
                    }
                }

                result.Add(elem, bookText);
            }

            return result;
        }
    }
}