From 17ed1954823b560a1fb601d5273cc900f713b178 Mon Sep 17 00:00:00 2001 From: verdoso Date: Fri, 14 Oct 2022 12:51:30 +0200 Subject: [PATCH] =?UTF-8?q?Evitamos=20quedarnos=20con=20la=20fecha=20de=20?= =?UTF-8?q?actualizaci=C3=B3n=20a=20null?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../librarian/services/BibliotecaService.java | 757 +++++++++--------- 1 file changed, 380 insertions(+), 377 deletions(-) diff --git a/src/main/java/org/greeneyed/epl/librarian/services/BibliotecaService.java b/src/main/java/org/greeneyed/epl/librarian/services/BibliotecaService.java index 048324f..ae8694d 100644 --- a/src/main/java/org/greeneyed/epl/librarian/services/BibliotecaService.java +++ b/src/main/java/org/greeneyed/epl/librarian/services/BibliotecaService.java @@ -58,381 +58,384 @@ @RequiredArgsConstructor(onConstructor = @__({ @Autowired })) public class BibliotecaService { - public static interface ElementOrdering { - QueryOptions getQueryOptionsAscending(); - - QueryOptions getQueryOptionsDescending(); - - SimpleAttribute getSortAttribute(); - } - - @Getter - @AllArgsConstructor - public enum IDIOMA_ORDERING implements ElementOrdering { - POR_IDIOMA(queryOptions(orderBy(ascending(Idioma.IDIOMA_NOMBRE))), - queryOptions(orderBy(descending(Idioma.IDIOMA_NOMBRE)))), - POR_LIBROS(queryOptions(orderBy(ascending(Idioma.IDIOMA_LIBROS))), - queryOptions(orderBy(descending(Idioma.IDIOMA_LIBROS)))); - - private final QueryOptions queryOptionsAscending; - private final QueryOptions queryOptionsDescending; - private final SimpleAttribute sortAttribute = Idioma.IDIOMA_NOMBRE; - - } - - @Getter - @AllArgsConstructor - public enum GENERO_ORDERING implements ElementOrdering { - POR_GENERO(queryOptions(orderBy(ascending(Genero.GENERO_NOMBRE))), - queryOptions(orderBy(descending(Genero.GENERO_NOMBRE)))), - POR_LIBROS(queryOptions(orderBy(ascending(Genero.GENERO_LIBROS))), - queryOptions(orderBy(descending(Genero.GENERO_LIBROS)))); - - private final QueryOptions queryOptionsAscending; - private final QueryOptions queryOptionsDescending; - private final SimpleAttribute sortAttribute = Genero.GENERO_NOMBRE; - } - - @Getter - @AllArgsConstructor - public enum AUTOR_ORDERING implements ElementOrdering { - POR_AUTOR(queryOptions(orderBy(ascending(Autor.AUTOR_NOMBRE))), - queryOptions(orderBy(descending(Autor.AUTOR_NOMBRE)))), - POR_LIBROS(queryOptions(orderBy(ascending(Autor.AUTOR_LIBROS))), - queryOptions(orderBy(descending(Autor.AUTOR_LIBROS)))); - - private final QueryOptions queryOptionsAscending; - private final QueryOptions queryOptionsDescending; - private final SimpleAttribute sortAttribute = Autor.AUTOR_NOMBRE; - } - - @Getter - @AllArgsConstructor - public enum BOOK_ORDERING implements ElementOrdering { - POR_TITULO(queryOptions(orderBy(ascending(Libro.LIBRO_TITULO))), - queryOptions(orderBy(descending(Libro.LIBRO_TITULO)))) - // - , POR_PUBLICADO(queryOptions(orderBy(ascending(Libro.LIBRO_PUBLICADO), ascending(Libro.LIBRO_TITULO))), - queryOptions(orderBy(descending(Libro.LIBRO_PUBLICADO), descending(Libro.LIBRO_TITULO)))) - // - , POR_CALIBRE(queryOptions(orderBy(ascending(Libro.LIBRO_EN_CALIBRE), ascending(Libro.LIBRO_TITULO))), - queryOptions(orderBy(descending(Libro.LIBRO_EN_CALIBRE), descending(Libro.LIBRO_TITULO)))) - // - , POR_AUTOR(queryOptions(orderBy(ascending(Libro.LIBRO_AUTOR))), - queryOptions(orderBy(descending(Libro.LIBRO_AUTOR)))) - // - , POR_IDIOMA(queryOptions(orderBy(ascending(Libro.LIBRO_IDIOMA))), - queryOptions(orderBy(descending(Libro.LIBRO_IDIOMA)))) - // - , - POR_COLECCION( - queryOptions(orderBy(ascending(Libro.LIBRO_COLECCION), ascending(Libro.LIBRO_VOLUMEN), - ascending(Libro.LIBRO_TITULO))), - queryOptions(orderBy(descending(Libro.LIBRO_COLECCION), descending(Libro.LIBRO_VOLUMEN), - descending(Libro.LIBRO_TITULO)))) - // - ; - - private final QueryOptions queryOptionsAscending; - private final QueryOptions queryOptionsDescending; - private final SimpleAttribute sortAttribute = Libro.LIBRO_TITULO; - } - - @Value("${git.build.version}") - private String buildVersion; - - private LocalDateTime fechaActualizacion = null; - - private final MapperService mapperService; - private final PreferencesService preferencesService; - private final CalibreService calibreService; - - private final IndexedCollection libreria = new ConcurrentIndexedCollection<>(); - private final IndexedCollection autores = new ConcurrentIndexedCollection<>(); - private final IndexedCollection generos = new ConcurrentIndexedCollection<>(); - private final IndexedCollection idiomas = new ConcurrentIndexedCollection<>(); - - private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); - private final WriteLock writeLock = lock.writeLock(); - private final ReadLock readLock = lock.readLock(); - - private Sumario sumario = null; - - @PostConstruct - public void postConstruct() { - libreria.addIndex(UniqueIndex.onAttribute(Libro.LIBRO_ID)); - libreria.addIndex(SuffixTreeIndex.onAttribute(Libro.LIBRO_TITULO)); - libreria.addIndex(SuffixTreeIndex.onAttribute(Libro.LIBRO_AUTOR)); - libreria.addIndex(SuffixTreeIndex.onAttribute(Libro.LIBRO_IDIOMA)); - libreria.addIndex(HashIndex.onAttribute(Libro.LIBRO_PUBLICADO)); - libreria.addIndex(SuffixTreeIndex.onAttribute(Libro.LIBRO_COLECCION)); - libreria.addIndex(SuffixTreeIndex.onAttribute(Libro.LIBRO_GENERO)); - libreria.addIndex(HashIndex.onAttribute(Libro.LIBRO_EN_CALIBRE)); - libreria.addIndex(HashIndex.onAttribute(Libro.LIBRO_AUTOR_FAVORITO)); - libreria.addIndex(HashIndex.onAttribute(Libro.LIBRO_IDIOMA_FAVORITO)); - libreria.addIndex(HashIndex.onAttribute(Libro.LIBRO_GENERO_FAVORITO)); - // - autores.addIndex(UniqueIndex.onAttribute(Autor.AUTOR_ID)); - autores.addIndex(SuffixTreeIndex.onAttribute(Autor.AUTOR_NOMBRE)); - // - generos.addIndex(UniqueIndex.onAttribute(Genero.GENERO_ID)); - generos.addIndex(SuffixTreeIndex.onAttribute(Genero.GENERO_NOMBRE)); - // - idiomas.addIndex(UniqueIndex.onAttribute(Idioma.IDIOMA_ID)); - idiomas.addIndex(SuffixTreeIndex.onAttribute(Idioma.IDIOMA_NOMBRE)); - // - log.info("Inicializando versi\u00f3n: {}", buildVersion); - } - - public void update(UpdateSpec updateSpec) { - writeLock.lock(); - try { - // Limpiamos y aƱadimos los elementos individuales para que no haya referencias - // sueltas - libreria.clear(); - final List libros = updateSpec.getLibroCSVs() - .stream() - .map(mapperService::from) - .collect(Collectors.toList()); - libreria.addAll(libros); - log.info("Libros a\u00f1adidos."); - // Actualizamos segun los datos que tenemos - calibreService.updateLibros(SEARCH_AND_UDPATE_BOOK); - actualizaAutoresPreferidos(preferencesService.getAutoresPreferidos()); - actualizaLibrosDescartados(preferencesService.getLibrosDescartados()); - actualizaIdiomasFavoritos(preferencesService.getIdiomasPreferidos()); - actualizaGenerosFavoritos(preferencesService.getGenerosPreferidos()); - // - autores.clear(); - autores.addAll(libreria.stream() - .map(Libro::getAutor) - .flatMap(autor -> Stream.of(autor.split(" & "))) - .map(String::trim) - .distinct() - .map(nombre -> { - try (final ResultSet queryResult = libreria - .retrieve(contains(Libro.LIBRO_AUTOR, Libro.flattenToAscii(nombre)))) { - return new Autor(nombre, queryResult.size()); - } - }) - .collect(Collectors.toList())); - // - generos.clear(); - generos.addAll(libreria.stream() - .flatMap(libro -> libro.getListaGeneros().stream()) - .map(String::trim) - .distinct() - .map(nombre -> { - try (final ResultSet queryResult = libreria - .retrieve(contains(Libro.LIBRO_GENERO, Libro.flattenToAscii(nombre)))) { - return new Genero(nombre, queryResult.size()); - } - }) - .collect(Collectors.toList())); - // - idiomas.clear(); - idiomas.addAll(libreria.stream().map(Libro::getIdioma).map(String::trim).distinct().map(nombre -> { - try (final ResultSet queryResult = libreria - .retrieve(contains(Libro.LIBRO_IDIOMA, Libro.flattenToAscii(nombre)))) { - return new Idioma(nombre, queryResult.size()); - } - }).collect(Collectors.toList())); - // - this.fechaActualizacion = updateSpec.getFechaActualizacion(); - log.info("Libros almacenados en la biblioteca: {}", libreria.size()); - // - // Inicializamos el sumario - sumario = null; - } finally { - writeLock.unlock(); - } - } - - public Sumario getSumario() { - if (sumario == null) { - int numLibros = libreria.size(); - int numIdiomas = (int) libreria.stream().map(Libro::getIdioma).distinct().count(); - int numAutores = (int) libreria.stream().map(Libro::getAutor).distinct().count(); - int numGeneros = (int) libreria.stream() - .map(Libro::getListaGeneros) - .flatMap(List::stream) - .filter(Objects::nonNull) - .distinct() - .count(); - sumario = new Sumario(buildVersion, - fechaActualizacion.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(), numLibros, numIdiomas, - numAutores, numGeneros, calibreService.isEnabled()); - } - return sumario; - } - - public Pagina paginaLibros(BusquedaLibro busquedaLibro) { - Pagina pagina = new Pagina<>(); - readLock.lock(); - try (final ResultSet queryResult = libreria.retrieve(busquedaLibro.getQuery(preferencesService), - busquedaLibro.getQueryOptions())) { - pagina.setTotal(queryResult.size()); - pagina.setResults(queryResult.stream() - .skip((busquedaLibro.getNumeroPagina() - 1) * (long) busquedaLibro.getPorPagina()) - .limit(busquedaLibro.getPorPagina()) - .collect(Collectors.toList())); - } finally { - readLock.unlock(); - } - return pagina; - } - - public Pagina paginaAutor(BusquedaElemento busquedaAutor) { - return paginaElementos(autores, busquedaAutor, preferencesService::checkAutorFavorito); - } - - public Pagina paginaGenero(BusquedaElemento busquedaGenero) { - return paginaElementos(generos, busquedaGenero, preferencesService::checkGeneroFavorito); - } - - public Pagina paginaIdioma(BusquedaElemento busquedaIdioma) { - return paginaElementos(idiomas, busquedaIdioma, preferencesService::checkIdiomaFavorito); - } - - private Pagina paginaElementos(IndexedCollection elementos, - BusquedaElemento busqueda, Function esFavorito) { - Pagina pagina = new Pagina<>(); - readLock.lock(); - try (final ResultSet queryResult = elementos.retrieve(busqueda.getQuery(), busqueda.getQueryOptions())) { - if (busqueda.isSoloFavoritos()) { - Predicate filterPredicate = object -> esFavorito.apply(object.getNombre()); - pagina.setTotal((int) queryResult.stream().filter(filterPredicate).count()); - pagina.setResults(queryResult.stream() - .filter(filterPredicate) - .skip((busqueda.getNumeroPagina() - 1) * (long) busqueda.getPorPagina()) - .limit(busqueda.getPorPagina()) - .peek(object -> object.setFavorito(true)) - .collect(Collectors.toList())); - } else { - pagina.setTotal(queryResult.size()); - pagina.setResults(queryResult.stream() - .skip((busqueda.getNumeroPagina() - 1) * (long) busqueda.getPorPagina()) - .limit(busqueda.getPorPagina()) - .peek(object -> object.setFavorito(esFavorito.apply(object.getNombre()))) - .collect(Collectors.toList())); - } - } finally { - readLock.unlock(); - } - return pagina; - } - - public void setDescarte(Integer libroId, boolean descartado) { - log.info("Actualizando libros descarte..."); - writeLock.lock(); - try { - try (final ResultSet queryResult = libreria.retrieve(in(Libro.LIBRO_ID, libroId))) { - queryResult.stream().forEach(libro -> { - libreria.remove(libro); - libro.setDescartado(descartado); - libreria.add(libro); - }); - } - } finally { - writeLock.unlock(); - } - log.info("...actualizado"); - } - - public void actualizaLibrosDescartados(Set libros) { - log.info("Actualizando libros descartados..."); - writeLock.lock(); - try { - List all = libreria.stream() - .peek(libro -> libro.setDescartado(libros.contains(libro.getId()))) - .collect(Collectors.toList()); - libreria.clear(); - libreria.addAll(all); - } finally { - writeLock.unlock(); - } - log.info("...actualizados"); - } - - public void actualizaAutoresPreferidos(Set autores) { - log.info("Actualizando autores preferidos..."); - writeLock.lock(); - try { - libreria.stream().forEach(libro -> libro.setAutorFavorito(false)); - Set normalisedAutors = autores.stream().map(Libro::flattenToAscii).collect(Collectors.toSet()); - try (final ResultSet queryResult = libreria.retrieve(in(Libro.LIBRO_AUTOR, normalisedAutors))) { - queryResult.stream().forEach(libro -> { - libro.setAutorFavorito(true); - }); - } - List all = libreria.stream().collect(Collectors.toList()); - libreria.clear(); - libreria.addAll(all); - } finally { - writeLock.unlock(); - } - log.info("...actualizados"); - } - - public void actualizaIdiomasFavoritos(Set idiomas) { - log.info("Actualizando idiomas preferidos..."); - writeLock.lock(); - try { - libreria.stream().forEach(libro -> libro.setIdiomaFavorito(false)); - Set normalisedIdiomas = idiomas.stream().map(Libro::flattenToAscii).collect(Collectors.toSet()); - try (final ResultSet queryResult = libreria.retrieve(in(Libro.LIBRO_IDIOMA, normalisedIdiomas))) { - queryResult.stream().forEach(libro -> { - libro.setIdiomaFavorito(true); - }); - } - List all = libreria.stream().collect(Collectors.toList()); - libreria.clear(); - libreria.addAll(all); - } finally { - writeLock.unlock(); - } - log.info("...actualizados"); - } - - public void actualizaGenerosFavoritos(Set generos) { - log.info("Actualizando generos preferidos..."); - writeLock.lock(); - try { - libreria.stream().forEach(libro -> libro.setGeneroFavorito(false)); - Set normalisedGeneros = generos.stream().map(Libro::flattenToAscii).collect(Collectors.toSet()); - try (final ResultSet queryResult = libreria.retrieve(in(Libro.LIBRO_GENERO, normalisedGeneros))) { - queryResult.stream().forEach(libro -> { - libro.setGeneroFavorito(true); - }); - } - List all = libreria.stream().collect(Collectors.toList()); - libreria.clear(); - libreria.addAll(all); - } finally { - writeLock.unlock(); - } - log.info("...actualizados"); - } - - private BiConsumer SEARCH_AND_UDPATE_BOOK = (titulo, autores) -> { - List aModificar = new ArrayList<>(); - Set autoresSet = Arrays.asList(autores.split(" & ")) - .stream() - .map(Libro::flattenToAscii) - .collect(Collectors.toSet()); - try (final com.googlecode.cqengine.resultset.ResultSet queryResult = libreria - .retrieve(BusquedaLibro.getPartialQuery(Libro.flattenToAscii(titulo), Libro.LIBRO_TITULO))) { - queryResult.stream().forEach(libro -> { - Set autoresSetLibro = libro.getListaAutores() - .stream() - .map(Libro::flattenToAscii) - .collect(Collectors.toSet()); - if (autoresSetLibro.containsAll(autoresSet) && autoresSet.containsAll(autoresSetLibro)) { - libro.setInCalibre(true); - aModificar.add(libro); - } - }); - } - libreria.update(aModificar, aModificar); - }; + public static interface ElementOrdering { + QueryOptions getQueryOptionsAscending(); + + QueryOptions getQueryOptionsDescending(); + + SimpleAttribute getSortAttribute(); + } + + @Getter + @AllArgsConstructor + public enum IDIOMA_ORDERING implements ElementOrdering { + POR_IDIOMA(queryOptions(orderBy(ascending(Idioma.IDIOMA_NOMBRE))), + queryOptions(orderBy(descending(Idioma.IDIOMA_NOMBRE)))), + POR_LIBROS(queryOptions(orderBy(ascending(Idioma.IDIOMA_LIBROS))), + queryOptions(orderBy(descending(Idioma.IDIOMA_LIBROS)))); + + private final QueryOptions queryOptionsAscending; + private final QueryOptions queryOptionsDescending; + private final SimpleAttribute sortAttribute = Idioma.IDIOMA_NOMBRE; + + } + + @Getter + @AllArgsConstructor + public enum GENERO_ORDERING implements ElementOrdering { + POR_GENERO(queryOptions(orderBy(ascending(Genero.GENERO_NOMBRE))), + queryOptions(orderBy(descending(Genero.GENERO_NOMBRE)))), + POR_LIBROS(queryOptions(orderBy(ascending(Genero.GENERO_LIBROS))), + queryOptions(orderBy(descending(Genero.GENERO_LIBROS)))); + + private final QueryOptions queryOptionsAscending; + private final QueryOptions queryOptionsDescending; + private final SimpleAttribute sortAttribute = Genero.GENERO_NOMBRE; + } + + @Getter + @AllArgsConstructor + public enum AUTOR_ORDERING implements ElementOrdering { + POR_AUTOR(queryOptions(orderBy(ascending(Autor.AUTOR_NOMBRE))), + queryOptions(orderBy(descending(Autor.AUTOR_NOMBRE)))), + POR_LIBROS(queryOptions(orderBy(ascending(Autor.AUTOR_LIBROS))), + queryOptions(orderBy(descending(Autor.AUTOR_LIBROS)))); + + private final QueryOptions queryOptionsAscending; + private final QueryOptions queryOptionsDescending; + private final SimpleAttribute sortAttribute = Autor.AUTOR_NOMBRE; + } + + @Getter + @AllArgsConstructor + public enum BOOK_ORDERING implements ElementOrdering { + POR_TITULO(queryOptions(orderBy(ascending(Libro.LIBRO_TITULO))), + queryOptions(orderBy(descending(Libro.LIBRO_TITULO)))) + // + , POR_PUBLICADO(queryOptions(orderBy(ascending(Libro.LIBRO_PUBLICADO), ascending(Libro.LIBRO_TITULO))), + queryOptions(orderBy(descending(Libro.LIBRO_PUBLICADO), descending(Libro.LIBRO_TITULO)))) + // + , POR_CALIBRE(queryOptions(orderBy(ascending(Libro.LIBRO_EN_CALIBRE), ascending(Libro.LIBRO_TITULO))), + queryOptions(orderBy(descending(Libro.LIBRO_EN_CALIBRE), descending(Libro.LIBRO_TITULO)))) + // + , POR_AUTOR(queryOptions(orderBy(ascending(Libro.LIBRO_AUTOR))), + queryOptions(orderBy(descending(Libro.LIBRO_AUTOR)))) + // + , POR_IDIOMA(queryOptions(orderBy(ascending(Libro.LIBRO_IDIOMA))), + queryOptions(orderBy(descending(Libro.LIBRO_IDIOMA)))) + // + , + POR_COLECCION( + queryOptions(orderBy(ascending(Libro.LIBRO_COLECCION), ascending(Libro.LIBRO_VOLUMEN), + ascending(Libro.LIBRO_TITULO))), + queryOptions(orderBy(descending(Libro.LIBRO_COLECCION), descending(Libro.LIBRO_VOLUMEN), + descending(Libro.LIBRO_TITULO)))) + // + ; + + private final QueryOptions queryOptionsAscending; + private final QueryOptions queryOptionsDescending; + private final SimpleAttribute sortAttribute = Libro.LIBRO_TITULO; + } + + @Value("${git.build.version}") + private String buildVersion; + + private LocalDateTime fechaActualizacion = null; + + private final MapperService mapperService; + private final PreferencesService preferencesService; + private final CalibreService calibreService; + + private final IndexedCollection libreria = new ConcurrentIndexedCollection<>(); + private final IndexedCollection autores = new ConcurrentIndexedCollection<>(); + private final IndexedCollection generos = new ConcurrentIndexedCollection<>(); + private final IndexedCollection idiomas = new ConcurrentIndexedCollection<>(); + + private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + private final WriteLock writeLock = lock.writeLock(); + private final ReadLock readLock = lock.readLock(); + + private Sumario sumario = null; + + @PostConstruct + public void postConstruct() { + libreria.addIndex(UniqueIndex.onAttribute(Libro.LIBRO_ID)); + libreria.addIndex(SuffixTreeIndex.onAttribute(Libro.LIBRO_TITULO)); + libreria.addIndex(SuffixTreeIndex.onAttribute(Libro.LIBRO_AUTOR)); + libreria.addIndex(SuffixTreeIndex.onAttribute(Libro.LIBRO_IDIOMA)); + libreria.addIndex(HashIndex.onAttribute(Libro.LIBRO_PUBLICADO)); + libreria.addIndex(SuffixTreeIndex.onAttribute(Libro.LIBRO_COLECCION)); + libreria.addIndex(SuffixTreeIndex.onAttribute(Libro.LIBRO_GENERO)); + libreria.addIndex(HashIndex.onAttribute(Libro.LIBRO_EN_CALIBRE)); + libreria.addIndex(HashIndex.onAttribute(Libro.LIBRO_AUTOR_FAVORITO)); + libreria.addIndex(HashIndex.onAttribute(Libro.LIBRO_IDIOMA_FAVORITO)); + libreria.addIndex(HashIndex.onAttribute(Libro.LIBRO_GENERO_FAVORITO)); + // + autores.addIndex(UniqueIndex.onAttribute(Autor.AUTOR_ID)); + autores.addIndex(SuffixTreeIndex.onAttribute(Autor.AUTOR_NOMBRE)); + // + generos.addIndex(UniqueIndex.onAttribute(Genero.GENERO_ID)); + generos.addIndex(SuffixTreeIndex.onAttribute(Genero.GENERO_NOMBRE)); + // + idiomas.addIndex(UniqueIndex.onAttribute(Idioma.IDIOMA_ID)); + idiomas.addIndex(SuffixTreeIndex.onAttribute(Idioma.IDIOMA_NOMBRE)); + // + log.info("Inicializando versi\u00f3n: {}", buildVersion); + } + + public void update(UpdateSpec updateSpec) { + writeLock.lock(); + try { + // Limpiamos y aƱadimos los elementos individuales para que no haya referencias + // sueltas + libreria.clear(); + final List libros = updateSpec.getLibroCSVs() + .stream() + .map(mapperService::from) + .collect(Collectors.toList()); + libreria.addAll(libros); + log.info("Libros a\u00f1adidos."); + // Actualizamos segun los datos que tenemos + calibreService.updateLibros(SEARCH_AND_UDPATE_BOOK); + actualizaAutoresPreferidos(preferencesService.getAutoresPreferidos()); + actualizaLibrosDescartados(preferencesService.getLibrosDescartados()); + actualizaIdiomasFavoritos(preferencesService.getIdiomasPreferidos()); + actualizaGenerosFavoritos(preferencesService.getGenerosPreferidos()); + // + autores.clear(); + autores.addAll(libreria.stream() + .map(Libro::getAutor) + .flatMap(autor -> Stream.of(autor.split(" & "))) + .map(String::trim) + .distinct() + .map(nombre -> { + try (final ResultSet queryResult = libreria + .retrieve(contains(Libro.LIBRO_AUTOR, Libro.flattenToAscii(nombre)))) { + return new Autor(nombre, queryResult.size()); + } + }) + .collect(Collectors.toList())); + // + generos.clear(); + generos.addAll(libreria.stream() + .flatMap(libro -> libro.getListaGeneros().stream()) + .map(String::trim) + .distinct() + .map(nombre -> { + try (final ResultSet queryResult = libreria + .retrieve(contains(Libro.LIBRO_GENERO, Libro.flattenToAscii(nombre)))) { + return new Genero(nombre, queryResult.size()); + } + }) + .collect(Collectors.toList())); + // + idiomas.clear(); + idiomas.addAll(libreria.stream().map(Libro::getIdioma).map(String::trim).distinct().map(nombre -> { + try (final ResultSet queryResult = libreria + .retrieve(contains(Libro.LIBRO_IDIOMA, Libro.flattenToAscii(nombre)))) { + return new Idioma(nombre, queryResult.size()); + } + }).collect(Collectors.toList())); + // + this.fechaActualizacion = updateSpec.getFechaActualizacion(); + if (this.fechaActualizacion == null) { + this.fechaActualizacion = LocalDateTime.now(); + } + log.info("Libros almacenados en la biblioteca: {}", libreria.size()); + // + // Inicializamos el sumario + sumario = null; + } finally { + writeLock.unlock(); + } + } + + public Sumario getSumario() { + if (sumario == null) { + int numLibros = libreria.size(); + int numIdiomas = (int) libreria.stream().map(Libro::getIdioma).distinct().count(); + int numAutores = (int) libreria.stream().map(Libro::getAutor).distinct().count(); + int numGeneros = (int) libreria.stream() + .map(Libro::getListaGeneros) + .flatMap(List::stream) + .filter(Objects::nonNull) + .distinct() + .count(); + sumario = new Sumario(buildVersion, + fechaActualizacion.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(), numLibros, numIdiomas, + numAutores, numGeneros, calibreService.isEnabled()); + } + return sumario; + } + + public Pagina paginaLibros(BusquedaLibro busquedaLibro) { + Pagina pagina = new Pagina<>(); + readLock.lock(); + try (final ResultSet queryResult = libreria.retrieve(busquedaLibro.getQuery(preferencesService), + busquedaLibro.getQueryOptions())) { + pagina.setTotal(queryResult.size()); + pagina.setResults(queryResult.stream() + .skip((busquedaLibro.getNumeroPagina() - 1) * (long) busquedaLibro.getPorPagina()) + .limit(busquedaLibro.getPorPagina()) + .collect(Collectors.toList())); + } finally { + readLock.unlock(); + } + return pagina; + } + + public Pagina paginaAutor(BusquedaElemento busquedaAutor) { + return paginaElementos(autores, busquedaAutor, preferencesService::checkAutorFavorito); + } + + public Pagina paginaGenero(BusquedaElemento busquedaGenero) { + return paginaElementos(generos, busquedaGenero, preferencesService::checkGeneroFavorito); + } + + public Pagina paginaIdioma(BusquedaElemento busquedaIdioma) { + return paginaElementos(idiomas, busquedaIdioma, preferencesService::checkIdiomaFavorito); + } + + private Pagina paginaElementos(IndexedCollection elementos, + BusquedaElemento busqueda, Function esFavorito) { + Pagina pagina = new Pagina<>(); + readLock.lock(); + try (final ResultSet queryResult = elementos.retrieve(busqueda.getQuery(), busqueda.getQueryOptions())) { + if (busqueda.isSoloFavoritos()) { + Predicate filterPredicate = object -> esFavorito.apply(object.getNombre()); + pagina.setTotal((int) queryResult.stream().filter(filterPredicate).count()); + pagina.setResults(queryResult.stream() + .filter(filterPredicate) + .skip((busqueda.getNumeroPagina() - 1) * (long) busqueda.getPorPagina()) + .limit(busqueda.getPorPagina()) + .peek(object -> object.setFavorito(true)) + .collect(Collectors.toList())); + } else { + pagina.setTotal(queryResult.size()); + pagina.setResults(queryResult.stream() + .skip((busqueda.getNumeroPagina() - 1) * (long) busqueda.getPorPagina()) + .limit(busqueda.getPorPagina()) + .peek(object -> object.setFavorito(esFavorito.apply(object.getNombre()))) + .collect(Collectors.toList())); + } + } finally { + readLock.unlock(); + } + return pagina; + } + + public void setDescarte(Integer libroId, boolean descartado) { + log.info("Actualizando libros descarte..."); + writeLock.lock(); + try { + try (final ResultSet queryResult = libreria.retrieve(in(Libro.LIBRO_ID, libroId))) { + queryResult.stream().forEach(libro -> { + libreria.remove(libro); + libro.setDescartado(descartado); + libreria.add(libro); + }); + } + } finally { + writeLock.unlock(); + } + log.info("...actualizado"); + } + + public void actualizaLibrosDescartados(Set libros) { + log.info("Actualizando libros descartados..."); + writeLock.lock(); + try { + List all = libreria.stream() + .peek(libro -> libro.setDescartado(libros.contains(libro.getId()))) + .collect(Collectors.toList()); + libreria.clear(); + libreria.addAll(all); + } finally { + writeLock.unlock(); + } + log.info("...actualizados"); + } + + public void actualizaAutoresPreferidos(Set autores) { + log.info("Actualizando autores preferidos..."); + writeLock.lock(); + try { + libreria.stream().forEach(libro -> libro.setAutorFavorito(false)); + Set normalisedAutors = autores.stream().map(Libro::flattenToAscii).collect(Collectors.toSet()); + try (final ResultSet queryResult = libreria.retrieve(in(Libro.LIBRO_AUTOR, normalisedAutors))) { + queryResult.stream().forEach(libro -> { + libro.setAutorFavorito(true); + }); + } + List all = libreria.stream().collect(Collectors.toList()); + libreria.clear(); + libreria.addAll(all); + } finally { + writeLock.unlock(); + } + log.info("...actualizados"); + } + + public void actualizaIdiomasFavoritos(Set idiomas) { + log.info("Actualizando idiomas preferidos..."); + writeLock.lock(); + try { + libreria.stream().forEach(libro -> libro.setIdiomaFavorito(false)); + Set normalisedIdiomas = idiomas.stream().map(Libro::flattenToAscii).collect(Collectors.toSet()); + try (final ResultSet queryResult = libreria.retrieve(in(Libro.LIBRO_IDIOMA, normalisedIdiomas))) { + queryResult.stream().forEach(libro -> { + libro.setIdiomaFavorito(true); + }); + } + List all = libreria.stream().collect(Collectors.toList()); + libreria.clear(); + libreria.addAll(all); + } finally { + writeLock.unlock(); + } + log.info("...actualizados"); + } + + public void actualizaGenerosFavoritos(Set generos) { + log.info("Actualizando generos preferidos..."); + writeLock.lock(); + try { + libreria.stream().forEach(libro -> libro.setGeneroFavorito(false)); + Set normalisedGeneros = generos.stream().map(Libro::flattenToAscii).collect(Collectors.toSet()); + try (final ResultSet queryResult = libreria.retrieve(in(Libro.LIBRO_GENERO, normalisedGeneros))) { + queryResult.stream().forEach(libro -> { + libro.setGeneroFavorito(true); + }); + } + List all = libreria.stream().collect(Collectors.toList()); + libreria.clear(); + libreria.addAll(all); + } finally { + writeLock.unlock(); + } + log.info("...actualizados"); + } + + private BiConsumer SEARCH_AND_UDPATE_BOOK = (titulo, autores) -> { + List aModificar = new ArrayList<>(); + Set autoresSet = Arrays.asList(autores.split(" & ")) + .stream() + .map(Libro::flattenToAscii) + .collect(Collectors.toSet()); + try (final com.googlecode.cqengine.resultset.ResultSet queryResult = libreria + .retrieve(BusquedaLibro.getPartialQuery(Libro.flattenToAscii(titulo), Libro.LIBRO_TITULO))) { + queryResult.stream().forEach(libro -> { + Set autoresSetLibro = libro.getListaAutores() + .stream() + .map(Libro::flattenToAscii) + .collect(Collectors.toSet()); + if (autoresSetLibro.containsAll(autoresSet) && autoresSet.containsAll(autoresSetLibro)) { + libro.setInCalibre(true); + aModificar.add(libro); + } + }); + } + libreria.update(aModificar, aModificar); + }; }