minor updates

This commit is contained in:
Dmitry Isaenko 2025-05-04 23:54:01 +03:00
parent 79a5a04488
commit 04db2d02f6
21 changed files with 104 additions and 159 deletions

View file

@ -5,7 +5,6 @@ import org.springframework.stereotype.Repository;
import ru.redrise.marinesco.library.Genre;
@Repository
public interface GenreRepository extends JpaRepository<Genre, String>{
}

View file

@ -7,5 +7,4 @@ import ru.redrise.marinesco.library.LibraryMetadata;
@Repository
public interface LibraryMetadataRepository extends CrudRepository<LibraryMetadata, Long>{
}

View file

@ -11,5 +11,5 @@ import ru.redrise.marinesco.security.UserRole.Type;
@Repository
public interface RolesRepository extends CrudRepository<UserRole, Long>{
public List<UserRole> findByType(Type type);
List<UserRole> findByType(Type type);
}

View file

@ -7,5 +7,5 @@ import ru.redrise.marinesco.User;
@Repository
public interface UserRepository extends CrudRepository<User, Long>{
public User findByUsername(String username);
User findByUsername(String username);
}

View file

@ -8,7 +8,7 @@ import ru.redrise.marinesco.data.AuthorRepository;
@Component
public class AthorByIdConverter implements Converter<Long, Author>{
private AuthorRepository authorRepository;
private final AuthorRepository authorRepository;
public AthorByIdConverter(AuthorRepository authorRepository){
this.authorRepository = authorRepository;

View file

@ -8,7 +8,7 @@ import ru.redrise.marinesco.data.GenreRepository;
@Component
public class GenreByIdConverter implements Converter<String, Genre>{
private GenreRepository genreRepository;
private final GenreRepository genreRepository;
public GenreByIdConverter(GenreRepository genreRepository){
this.genreRepository = genreRepository;

View file

@ -12,9 +12,9 @@ public class InpxLibraryMetadataScanner {
private InpxLibraryMetadataScanner() { }
public static LibraryMetadata saveFromFile(File inpxFile, LibraryMetadataRepository repository) throws Exception {
LibraryMetadata libraryMetadata = new LibraryMetadata();
var libraryMetadata = new LibraryMetadata();
try (ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(inpxFile))) {
try (var zipInputStream = new ZipInputStream(new FileInputStream(inpxFile))) {
ZipEntry zipEntry;
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
@ -37,8 +37,8 @@ public class InpxLibraryMetadataScanner {
}
private static String readPlainText(ZipInputStream zipInputStream) throws Exception {
byte[] content = new byte[1024];
StringBuilder stringBuilder = new StringBuilder();
var content = new byte[1024];
var stringBuilder = new StringBuilder();
while (zipInputStream.read(content) > 0)
stringBuilder.append(new String(content, StandardCharsets.UTF_8));

View file

@ -25,13 +25,12 @@ public class InpxScanner {
private static volatile String lastRunErrors = "";
private final ThreadPoolTaskExecutor executor;
private final String filesLocation;
private final AuthorRepository authorRepository;
private final GenreRepository genreRepository;
private final BookRepository bookRepository;
private final LibraryMetadataRepository libraryMetadataRepository;
private final String filesLocation;
public InpxScanner(ThreadPoolTaskExecutor executor,
ApplicationSettings applicationSettings,
AuthorRepository authorRepository,
@ -81,7 +80,7 @@ public class InpxScanner {
}
private File getInpxFile() throws Exception {
final FileSystemResource libraryLocation = new FileSystemResource(filesLocation);
var libraryLocation = new FileSystemResource(filesLocation);
return Arrays.stream(libraryLocation.getFile().listFiles())
.filter(file -> file.getName().endsWith(".inpx"))
.findFirst()
@ -89,8 +88,8 @@ public class InpxScanner {
}
private HashMap<String, byte[]> collectInp(File inpxFile) throws Exception {
final HashMap<String, byte[]> inpEntries = new HashMap<>();
try (ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(inpxFile))) {
var inpEntries = new HashMap<String, byte[]>();
try (var zipInputStream = new ZipInputStream(new FileInputStream(inpxFile))) {
ZipEntry zipEntry;
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
if (isInp(zipEntry)) {
@ -108,7 +107,7 @@ public class InpxScanner {
}
private byte[] inpToByteArray(ZipInputStream stream, long fileSize) throws Exception {
ByteBuffer inpByteBuffer = ByteBuffer.allocate((int) fileSize);
var inpByteBuffer = ByteBuffer.allocate((int) fileSize);
int blockSize = 0x200;
if (fileSize < 0x200)
blockSize = (int) fileSize;
@ -185,7 +184,7 @@ public class InpxScanner {
}
saveAll(books, authors, genres);
} catch (Exception e) {
log.error("{}", e);
log.error(e.toString());
lastRunErrors = lastRunErrors + " " + e.getMessage();
}
}

View file

@ -37,7 +37,7 @@ public class LibraryMetadata {
}
public void setCollectionInfo(String content) throws Exception {
String[] lines = content.split("\n");
var lines = content.split("\n");
if (lines.length < 4)
throw new Exception("Invalid 'collection.info' file. It contains only "+lines.length+" lines!");
libraryName = lines[0].trim();

View file

@ -15,35 +15,28 @@ import ru.redrise.marinesco.library.Author;
@RequestMapping(path = "/api/author",
produces = "application/json")
public class AuthorsApiController {
private AuthorRepository authorRepository;
private final AuthorRepository authorRepository;
public AuthorsApiController(AuthorRepository authorRepository){
this.authorRepository = authorRepository;
}
@GetMapping
public Iterable<Author> getAuthors(
@RequestParam(value = "page", required = false, defaultValue = "0") Integer page,
@RequestParam(value = "sort", required = false, defaultValue = "authorName") String sortBy){
PageRequest pageRequest = PageRequest.of(
page, 10, Sort.by(sortBy).descending());
public Iterable<Author> getAuthors(@RequestParam(value = "page", required = false, defaultValue = "0") Integer page,
@RequestParam(value = "sort", required = false, defaultValue = "authorName") String sortBy) {
var pageRequest = PageRequest.of(page, 10, Sort.by(sortBy).descending());
return authorRepository.findAll(pageRequest).getContent();
}
@GetMapping("/by/name/{name}")
public Iterable<Author> getAuthorId(
@PathVariable("name") String authorName,
@RequestParam(value = "page", required = false, defaultValue = "0") Integer page){
PageRequest pageRequest = PageRequest.of(page, 10);
public Iterable<Author> getAuthorId(@PathVariable("name") String authorName,
@RequestParam(value = "page", required = false, defaultValue = "0") Integer page) {
var pageRequest = PageRequest.of(page, 10);
return authorRepository.findByAuthorNameContainingIgnoreCase(authorName, pageRequest);
}
@GetMapping("/by/id/{id}")
public Author getAuthorId(@PathVariable("id") Long authorId){
return authorRepository.findById(authorId).get();
}
}

View file

@ -17,7 +17,7 @@ import ru.redrise.marinesco.library.Book;
@RequestMapping(path = "/api/book",
produces = "application/json")
public class BooksApiController {
private BookRepository bookRepository ;
private final BookRepository bookRepository ;
public BooksApiController(BookRepository bookRepository){
this.bookRepository = bookRepository;
@ -30,33 +30,23 @@ public class BooksApiController {
}
@GetMapping(params = "page")
public Iterable<Book> getBooks(
@RequestParam(value = "page", required = true) Integer page,
public Iterable<Book> getBooks(@RequestParam(value = "page", required = true) Integer page,
@RequestParam(value = "sort", required = false, defaultValue = "title") String sortBy){
PageRequest pageRequest = PageRequest.of(
page, 10, Sort.by(sortBy).descending());
var pageRequest = PageRequest.of(page, 10, Sort.by(sortBy).descending());
return bookRepository.findAll(pageRequest).getContent();
}
@GetMapping("/by/title/{title}")
public Iterable<Book> getBooksByName(
@PathVariable("title") String title,
public Iterable<Book> getBooksByName(@PathVariable("title") String title,
@RequestParam(value = "page", required = false, defaultValue = "0") Integer page){
PageRequest pageRequest = PageRequest.of(page, 10);
var pageRequest = PageRequest.of(page, 10);
return bookRepository.findByTitleContainingIgnoreCase(title, pageRequest);
}
@GetMapping("/by/series/{series}")
public Iterable<Book> getBooksBySeries(
@PathVariable("series") String series,
public Iterable<Book> getBooksBySeries(@PathVariable("series") String series,
@RequestParam(value = "page", required = false, defaultValue = "0") Integer page){
PageRequest pageRequest = PageRequest.of(page, 10);
var pageRequest = PageRequest.of(page, 10);
return bookRepository.findBySeriesContainingIgnoreCase(series, pageRequest);
}

View file

@ -24,18 +24,16 @@ import ru.redrise.marinesco.library.Genre;
@RestController
@RequestMapping(path = "/api/genres", produces = "application/json")
public class GenresApiController {
private GenreRepository genreRepository;
private final GenreRepository genreRepository;
public GenresApiController(GenreRepository genreRepository) {
this.genreRepository = genreRepository;
}
@GetMapping
public Iterable<Genre> getGenres(
@RequestParam(value = "page", required = false, defaultValue = "0") Integer page,
public Iterable<Genre> getGenres(@RequestParam(value = "page", required = false, defaultValue = "0") Integer page,
@RequestParam(value = "sort", required = false, defaultValue = "genreId") String sortBy) {
PageRequest pageRequest = PageRequest.of(page, 10, Sort.by(sortBy).descending());
var pageRequest = PageRequest.of(page, 10, Sort.by(sortBy).descending());
return genreRepository.findAll(pageRequest).getContent();
}

View file

@ -1,13 +1,10 @@
package ru.redrise.marinesco.library.settings;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
@ -21,7 +18,6 @@ import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import ru.redrise.marinesco.data.GenreRepository;
import ru.redrise.marinesco.library.Genre;
import org.springframework.web.bind.annotation.RequestBody;
@Slf4j
@ -30,7 +26,7 @@ import org.springframework.web.bind.annotation.RequestBody;
@PreAuthorize("hasRole('ADMIN')")
public class GenreSettingsController {
private GenreRepository genreRepository;
private final GenreRepository genreRepository;
public GenreSettingsController(GenreRepository genreRepository) {
this.genreRepository = genreRepository;
@ -45,8 +41,7 @@ public class GenreSettingsController {
public GenresHolder setRegistrationSetting() {
List<Genre> genres = new ArrayList<>();
genreRepository.findAll()
.iterator()
genreRepository.findAll().iterator()
.forEachRemaining(genres::add);
return new GenresHolder(genres);
@ -65,14 +60,10 @@ public class GenreSettingsController {
}
@PostMapping("/upload")
public String postMethodName(@RequestParam("file") MultipartFile file,
public String postUpload(@RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes) {
final String message = GenresUpload.upload(file.getResource(), file.getSize(), genreRepository);
var message = GenresUpload.upload(file, genreRepository);
redirectAttributes.addFlashAttribute("message", message);
return "redirect:/settings/genres";
}
}

View file

@ -3,24 +3,20 @@ package ru.redrise.marinesco.library.settings;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.springframework.core.io.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import ru.redrise.marinesco.data.GenreRepository;
import ru.redrise.marinesco.library.Genre;
@Slf4j
public class GenresUpload {
public static String upload(Resource resource, long fileSize, GenreRepository repository) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()))){
if (fileSize == 0)
throw new Exception("empty file");
public static String upload(MultipartFile file, GenreRepository repository) {
try (var reader = new BufferedReader(new InputStreamReader(file.getInputStream()))){
String line;
List<Genre> genres = new ArrayList<>();
var genres = new ArrayList<Genre>();
while ((line = reader.readLine()) != null) {
String[] arr = line.split(":::");
@ -36,6 +32,6 @@ public class GenresUpload {
return "Upload failed: " + e.getMessage();
}
return "Successfully uploaded: " + resource.getFilename();
return "Successfully uploaded: " + file.getResource().getFilename();
}
}

View file

@ -1,8 +1,6 @@
package ru.redrise.marinesco.library.web;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
@ -11,7 +9,6 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import ru.redrise.marinesco.data.AuthorRepository;
import ru.redrise.marinesco.library.Author;
import ru.redrise.marinesco.library.Book;
@Controller
@ -25,15 +22,14 @@ public class AuthorController {
@GetMapping("/{authorId}")
public String getPage(@PathVariable("authorId") Long authorId, Model model) {
final Author author = authorRepository.findById(authorId).orElse(null);
var author = authorRepository.findById(authorId).orElse(null);
if (author == null){
model.addAttribute("Error", "Not found");
return "author";
}
List<Book> books = author.getBooks();
var books = author.getBooks();
books.sort(Comparator.comparing(Book::getSeries));
model.addAttribute("author", author)

View file

@ -20,7 +20,8 @@ public class BookController {
@GetMapping("/{bookId}")
public String getPage(@PathVariable("bookId") Integer bookId, Model model) {
Book book = bookRepository.findById(bookId).orElse(null);
var book = bookRepository.findById(bookId).orElse(null);
if (book == null){
model.addAttribute("Error", "Not found");
return "book";

View file

@ -33,10 +33,12 @@ public class DownloadController {
public void getMethodName(@RequestParam String container,
@RequestParam String file,
HttpServletResponse response) throws Exception {
try {
File bookFile = new File(filesLocation + File.separator + container + File.separator + file);
var bookFile = new File(filesLocation + File.separator + container + File.separator + file);
if (! bookFile.exists())
throw new Exception("No file found :[");
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
ContentDisposition.attachment()
@ -44,10 +46,9 @@ public class DownloadController {
.build()
.toString());
try (ServletOutputStream outStream = response.getOutputStream();
FileInputStream inputStream = new FileInputStream(bookFile)) {
try (var outStream = response.getOutputStream();
var inputStream = new FileInputStream(bookFile)) {
IOUtils.copy(inputStream, outStream);
}
} catch (Exception e) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Book not found [" + e.getMessage() + "]");
}

View file

@ -1,7 +1,5 @@
package ru.redrise.marinesco.library.web;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@ -11,19 +9,17 @@ import org.springframework.web.bind.annotation.RequestParam;
import lombok.extern.slf4j.Slf4j;
import ru.redrise.marinesco.data.AuthorRepository;
import ru.redrise.marinesco.data.BookRepository;
import ru.redrise.marinesco.library.Author;
import ru.redrise.marinesco.library.Book;
@Slf4j
@Controller
@RequestMapping("/search")
public class SearchController {
private final BookRepository inpEntryRepository;
private final BookRepository booksRepository;
private final AuthorRepository authorRepository;
public SearchController(BookRepository bookRepository, AuthorRepository authorRepository){
this.inpEntryRepository = bookRepository;
this.booksRepository = bookRepository;
this.authorRepository = authorRepository;
}
@ -33,39 +29,25 @@ public class SearchController {
@RequestParam(value = "series", required = false) Boolean series,
@RequestParam(value = "author", required = false) Boolean author,
Model model) {
model.addAttribute("searchPattern", search)
.addAttribute("isTitle", title)
.addAttribute("isSeries", series)
.addAttribute("isAuthor", author);
if (search.trim().isEmpty())
return "search";
model.addAttribute("searchPattern", search);
if (search.length() < 4){
if (search.isBlank() || search.length() < 4){
model.addAttribute("error", "Should be at least 4 chars");
return "search";
}
if (title != null){
List<Book> books = inpEntryRepository.findByTitleContainingIgnoreCase(search);
if (!books.isEmpty())
model.addAttribute("books", books);
model.addAttribute("isTitle", true);
}
if (title != null && title)
model.addAttribute("books", booksRepository.findByTitleContainingIgnoreCase(search));
if (series != null){
List<Book> bookSeries = inpEntryRepository.findBySeriesContainingIgnoreCase(search);
if (!bookSeries.isEmpty())
model.addAttribute("series", bookSeries);
model.addAttribute("isSeries", true);
}
if (series != null && series)
model.addAttribute("series", booksRepository.findBySeriesContainingIgnoreCase(search));
if (author != null){
List<Author> authors = authorRepository.findByAuthorNameContainingIgnoreCase(search);
if (!authors.isEmpty())
model.addAttribute("authors", authors);
model.addAttribute("isAuthor", true);
}
if (author != null && author)
model.addAttribute("authors", authorRepository.findByAuthorNameContainingIgnoreCase(search));
return "search";
}
}

View file

@ -12,7 +12,7 @@ import ru.redrise.marinesco.User;
//TODO: refactor along with RegistrationForm.java
@Data
public class AdministatorAddUserForm {
public class AdministratorAddUserForm {
@NotNull
@Size(min=3, max=32, message="Username must be at least 3 characters long. Should not exceed 32 characters.")

View file

@ -47,7 +47,7 @@ public class ManageUsersController {
@ModelAttribute
public void addTitle(Model model) {
model.addAttribute("header_text", "Manage users");
model.addAttribute("administatorAddUserForm", new AdministatorAddUserForm());
model.addAttribute("administratorAddUserForm", new AdministratorAddUserForm());
}
@ModelAttribute
@ -103,7 +103,7 @@ public class ManageUsersController {
}
@PostMapping
public String processNewUser(@Valid AdministatorAddUserForm form, Errors errors, Model model) {
public String processNewUser(@Valid AdministratorAddUserForm form, Errors errors, Model model) {
if (userRepository.findByUsername(form.getUsername()) != null) {
model.addAttribute("loginOccupied", "Login already in use. Please choose another one");
return "manage_users";

View file

@ -44,7 +44,7 @@
</div>
<hr>
<b>Add user</b>
<form method="POST" th:action="@{/settings/manage_users}" th:object="${administatorAddUserForm}">
<form method="POST" th:action="@{/settings/manage_users}" th:object="${administratorAddUserForm}">
<span class="validationError" th:if="${loginOccupied} != null" th:text="${loginOccupied}">pew</span>
<span class="validationError" th:if="${#fields.hasErrors('username')}"
th:errors="*{username}">Error</span>