diff --git a/UserselidrAppDataLocalTempA_study_of_the_safety_immunology_virolog-references.txt b/UserselidrAppDataLocalTempA_study_of_the_safety_immunology_virolog-references.txt deleted file mode 100644 index e4e16e47dc903d046dbfce53f951b392cdbfb57e..0000000000000000000000000000000000000000 --- a/UserselidrAppDataLocalTempA_study_of_the_safety_immunology_virolog-references.txt +++ /dev/null @@ -1 +0,0 @@ -"hahahahahahaha" \ No newline at end of file diff --git "a/UserselidrAppDataLocalTemp\302\263661.263675-references.txt" "b/UserselidrAppDataLocalTemp\302\263661.263675-references.txt" deleted file mode 100644 index 83c274254ec158b2a4435fc682e24ae923bd65c3..0000000000000000000000000000000000000000 --- "a/UserselidrAppDataLocalTemp\302\263661.263675-references.txt" +++ /dev/null @@ -1 +0,0 @@ -"heeeeeeeeeeeeeeeeeeej" \ No newline at end of file diff --git a/pom.xml b/pom.xml index dc68618947fdd6b25a373e0d3392cdbe078815fb..6f43c062409d9d282334047fe9f250288a3a61c2 100644 --- a/pom.xml +++ b/pom.xml @@ -28,6 +28,8 @@ </scm> <properties> <java.version>17</java.version> + <lombok.version>1.18.36</lombok.version> + </properties> <!-- --> @@ -41,32 +43,21 @@ <dependencies> <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-data-jpa</artifactId> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>${lombok.version}</version> + <scope>provided</scope> </dependency> + <dependency> <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-web</artifactId> - </dependency> - - <!--<dependency> - <groupId>com.mysql</groupId> - <artifactId>mysql-connector-j</artifactId> - <scope>runtime</scope> + <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> - <groupId>org.xerial</groupId> - <artifactId>sqlite-jdbc</artifactId> - <version>3.43.2.1</version> - </dependency> - - <dependency> - <groupId>org.hibernate.orm</groupId> - <artifactId>hibernate-community-dialects</artifactId> - <version>6.2.12.Final</version> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> </dependency> - --> <dependency> <groupId>com.h2database</groupId> @@ -79,8 +70,6 @@ <artifactId>spring-boot-starter-webflux</artifactId> </dependency> - - <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> @@ -93,12 +82,14 @@ <artifactId>tika-core</artifactId> <version>2.9.2</version> </dependency> + <dependency> <groupId>org.apache.tika</groupId> <artifactId>tika-parsers</artifactId> <version>2.9.2</version> <type>pom</type> </dependency> + <dependency> <groupId>org.apache.tika</groupId> <artifactId>tika-parser-pdf-module</artifactId> @@ -147,14 +138,6 @@ <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> - <!-- GROBID Dependencies - stará verzia - <dependency> - <groupId>org.grobid</groupId> - <artifactId>grobid-core</artifactId> - <version>0.8.1</version> - </dependency> - --> - <!-- Apache Commons IO (pre prácu so sĂşbormi) --> <dependency> <groupId>commons-io</groupId> @@ -183,13 +166,22 @@ <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> + <failOnError>false</failOnError> + <annotationProcessorPaths> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.6.3</version> </path> + + <path> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>${lombok.version}</version> + </path> </annotationProcessorPaths> + </configuration> </plugin> </plugins> diff --git a/src/main/java/com/dre0059/articleprocessor/GrobidClient.java b/src/main/java/com/dre0059/articleprocessor/GrobidClient.java index 4b52d743885498178c707895bd0d54918dee2100..7b58e41e4fb2e40d432509c7d20b60eb0c677cfc 100644 --- a/src/main/java/com/dre0059/articleprocessor/GrobidClient.java +++ b/src/main/java/com/dre0059/articleprocessor/GrobidClient.java @@ -1,5 +1,7 @@ package com.dre0059.articleprocessor; +import com.dre0059.articleprocessor.config.GrobidProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.BodyInserters; @@ -14,9 +16,10 @@ import java.io.File; public class GrobidClient { private final WebClient webClient; - public GrobidClient() { - this.webClient = WebClient.builder() - .baseUrl("http://158.196.98.65:8080") // URL kde bežà GROBID server + public GrobidClient(GrobidProperties grobidProperties) { + + this.webClient = WebClient.builder() + .baseUrl(grobidProperties.getHost()) // URL kde bežà GROBID server .build(); } diff --git a/src/main/java/com/dre0059/articleprocessor/apacheTika/PDFbox.java b/src/main/java/com/dre0059/articleprocessor/apacheTika/PDFbox.java index f520ae58f0bacb7e6daff7db441b37cb9a8da53d..fb4481081e0dd42f1e96d43d8e85244e1aaa42cb 100644 --- a/src/main/java/com/dre0059/articleprocessor/apacheTika/PDFbox.java +++ b/src/main/java/com/dre0059/articleprocessor/apacheTika/PDFbox.java @@ -1,14 +1,11 @@ package com.dre0059.articleprocessor.apacheTika; -import org.apache.pdfbox.pdmodel.PDDocument; -import org.apache.pdfbox.text.PDFTextStripper; -import org.springframework.stereotype.Component; - import java.io.File; import java.io.FileWriter; import java.io.IOException; - -import static com.lowagie.text.html.HtmlTagMap.isTitle; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.text.PDFTextStripper; +import org.springframework.stereotype.Component; @Component public class PDFbox { diff --git a/src/main/java/com/dre0059/articleprocessor/apacheTika/ReferencesScanner.java b/src/main/java/com/dre0059/articleprocessor/apacheTika/ReferencesScanner.java index 279e40509468c80b466c0148cd09c62811cdc801..d02dafd2cf1b4fded61e144a79348c52f0204bb2 100644 --- a/src/main/java/com/dre0059/articleprocessor/apacheTika/ReferencesScanner.java +++ b/src/main/java/com/dre0059/articleprocessor/apacheTika/ReferencesScanner.java @@ -1,15 +1,16 @@ package com.dre0059.articleprocessor.apacheTika; -import org.apache.tika.Tika; -import org.apache.tika.exception.TikaException; - -import javax.sound.midi.Soundbank; -import java.io.*; -import java.util.ArrayList; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; import java.util.Scanner; import java.util.Vector; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.tika.Tika; +import org.apache.tika.exception.TikaException; public class ReferencesScanner { diff --git a/src/main/java/com/dre0059/articleprocessor/controller/DocumentController.java b/src/main/java/com/dre0059/articleprocessor/controller/DocumentController.java index 5529c3aa90eb357b528987733cc09945761cd61c..4bb5031f85bfb9f709ba063d045d750499b8b609 100644 --- a/src/main/java/com/dre0059/articleprocessor/controller/DocumentController.java +++ b/src/main/java/com/dre0059/articleprocessor/controller/DocumentController.java @@ -4,48 +4,64 @@ import com.dre0059.articleprocessor.dto.DocumentDto; import com.dre0059.articleprocessor.dto.SimpleDocumentDto; import com.dre0059.articleprocessor.service.DocumentService; import java.util.List; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; -@Controller() -@RequestMapping("/api/document") +@Controller +@RequestMapping public class DocumentController { private final DocumentService documentService; - public DocumentController(DocumentService documentService) { this.documentService = documentService; } - @GetMapping("/{id}") + @GetMapping("/api/documents/{id}") public ResponseEntity<DocumentDto> getDocumentById(@PathVariable Long id) { return ResponseEntity.ok(documentService.getDocumentById(id)); } - @GetMapping("/references/{id}") + @GetMapping( + value = "/api/documents/{id}/content", + produces = MediaType.APPLICATION_PDF_VALUE + ) + public @ResponseBody byte[] getDocumentContentById(@PathVariable Long id) { + return documentService.getDocumentContentById(id).getContent(); + } + + @GetMapping("/api/documents/{id}/references") public ResponseEntity<List<SimpleDocumentDto>> getReferencesFromDocument(@PathVariable Long id) { - return ResponseEntity.ok(documentService.getDocumentReferences(id)); + return ResponseEntity.ok(documentService.getReferencedDocumentsById(id)); } @GetMapping("/view/{id}") - public String viewPdf(Model model, @PathVariable("id") Long id) { - var references = documentService.getDocumentReferences(id); + public String viewDocument(Model model, @PathVariable("id") Long id) { + var references = documentService.getReferencedDocumentsById(id); + if (documentService.getDocumentById(id) == null) { + throw new IllegalArgumentException("Document with ID " + id + " not found."); + } + + model.addAttribute("documentId", id); model.addAttribute("references", references); + model.addAttribute("docTitle", documentService.getDocumentById(id).getTitle()); + return "view-pdf"; } @GetMapping("/view") - public String viewPdf(Model model) { - var references = documentService.getAllReferences(); + public String viewAllDocuments(Model model) { + var documents = documentService.getAllDocuments(); - model.addAttribute("references", references); + model.addAttribute("documents", documents); return "view-all"; } diff --git a/src/main/java/com/dre0059/articleprocessor/controller/FileUploadController.java b/src/main/java/com/dre0059/articleprocessor/controller/FileUploadController.java index b5e1d07c7139a5acd349123c7f15ffffc29ac987..42addb697ecc78f7f849abbd1b45b3b5e136419b 100644 --- a/src/main/java/com/dre0059/articleprocessor/controller/FileUploadController.java +++ b/src/main/java/com/dre0059/articleprocessor/controller/FileUploadController.java @@ -1,57 +1,53 @@ package com.dre0059.articleprocessor.controller; import com.dre0059.articleprocessor.GrobidClient; -import com.dre0059.articleprocessor.model.Category; -import com.dre0059.articleprocessor.repository.CategoryRepository; +import com.dre0059.articleprocessor.service.CategoryService; import com.dre0059.articleprocessor.service.HeaderService; - import com.dre0059.articleprocessor.service.ReferenceService; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.List; -import java.util.Optional; - @Controller -@RequestMapping("/api/grobid") +@RequestMapping public class FileUploadController { private final GrobidClient grobidClient; private final HeaderService headerService; private final ReferenceService referenceService; - private final CategoryRepository categoryRepository; + private final CategoryService categoryService; - public FileUploadController(GrobidClient grobidClient, HeaderService headerService, ReferenceService referenceService, CategoryRepository categoryRepository) { + public FileUploadController(GrobidClient grobidClient, HeaderService headerService, ReferenceService referenceService, CategoryService categoryService) { this.grobidClient = grobidClient; this.headerService = headerService; this.referenceService = referenceService; - this.categoryRepository = categoryRepository; + this.categoryService = categoryService; } @GetMapping("/upload") public String showUploadForm(Model model) { - List<Category> categories = categoryRepository.findAll(); + var categories = categoryService.getAll(); model.addAttribute("categories", categories); return "upload"; // vracia upload.html } - @PostMapping("/upload") + @PostMapping("/api/upload") @ResponseBody - public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file, @RequestParam("category") String category) { + public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file, @RequestParam("categoryId") String categoryId) { if (file.isEmpty()) { return ResponseEntity.badRequest().body("No file uploaded!"); } - System.out.println("Received file: " + file.getOriginalFilename()); - System.out.println("Received category: " + category); - try { - // Vytvorenie doÄŤasnĂ©ho sĂşboru + System.out.println("Processing file " + file.getOriginalFilename()); File tmpFile = File.createTempFile("article-", ".pdf"); // save data from file to tmpFile @@ -60,26 +56,19 @@ public class FileUploadController { } catch (IOException e) { return ResponseEntity.internalServerError().body("FAILURE - cannot process file : " + e.getMessage()); } + //System.out.println("File written to temporary location. "); String header = grobidClient.processHeader(tmpFile); - String references = grobidClient.processReferences(tmpFile); + //System.out.println("GROBID Header processed: " + header); - String categoryId = category.substring(0, 3); - Optional<Category> categoryOptional = categoryRepository.findById(categoryId); + String references = grobidClient.processReferences(tmpFile); + //System.out.println("GROBID Reference processed: " + references); - System.out.println("ID category is : " + categoryId); - System.out.println("Optional category is : " + categoryOptional); - if (category.isEmpty()) { - return ResponseEntity.badRequest().body("Invalid category ID!"); - } + headerService.processHeader(header, categoryId, tmpFile); + //System.out.println("Header saved to database."); - headerService.processHeader(header, categoryOptional); referenceService.extractReferences(references); - - //System.out.println(header); - //System.out.println(references); - - + //System.out.println("References extracted.."); tmpFile.delete(); diff --git a/src/main/java/com/dre0059/articleprocessor/dto/DocumentDto.java b/src/main/java/com/dre0059/articleprocessor/dto/DocumentDto.java index 8f97cc0a80cb3e3ff89184df8b13b46fff9ee5d2..95d2875498e020efdc732fd52b475539b69c13d0 100644 --- a/src/main/java/com/dre0059/articleprocessor/dto/DocumentDto.java +++ b/src/main/java/com/dre0059/articleprocessor/dto/DocumentDto.java @@ -1,5 +1,10 @@ package com.dre0059.articleprocessor.dto; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter public class DocumentDto { private Long id; private String title; @@ -10,67 +15,5 @@ public class DocumentDto { private String publisher; private String target; - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public Integer getPublicationYear() { - return publicationYear; - } - - public void setPublicationYear(Integer publicationYear) { - this.publicationYear = publicationYear; - } - - public String getDoi() { - return doi; - } - - public void setDoi(String doi) { - this.doi = doi; - } - - public String getAbstractText() { - return abstractText; - } - - public void setAbstractText(String abstractText) { - this.abstractText = abstractText; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } - - public String getPublisher() { - return publisher; - } - - public void setPublisher(String publisher) { - this.publisher = publisher; - } - - public String getTarget() { - return target; - } - public void setTarget(String target) { - this.target = target; - } } diff --git a/src/main/java/com/dre0059/articleprocessor/dto/SimpleDocumentDto.java b/src/main/java/com/dre0059/articleprocessor/dto/SimpleDocumentDto.java index 9ed6b674f30bd38a295e87fe873303f1fc7dccbc..ea44d6b9b3e9a14e887084308020c13fea0ce3f7 100644 --- a/src/main/java/com/dre0059/articleprocessor/dto/SimpleDocumentDto.java +++ b/src/main/java/com/dre0059/articleprocessor/dto/SimpleDocumentDto.java @@ -1,26 +1,16 @@ package com.dre0059.articleprocessor.dto; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter public class SimpleDocumentDto { private Long id; private String title; + private String status; public String getLink() { return "/api/document/"+getId(); } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } } diff --git a/src/main/java/com/dre0059/articleprocessor/mapper/DocumentMapper.java b/src/main/java/com/dre0059/articleprocessor/mapper/DocumentMapper.java index 2a5516c35ff4603e90d1164743deff8f90224afe..854bab14f670c821492d945d9577e8668b971717 100644 --- a/src/main/java/com/dre0059/articleprocessor/mapper/DocumentMapper.java +++ b/src/main/java/com/dre0059/articleprocessor/mapper/DocumentMapper.java @@ -1,16 +1,31 @@ package com.dre0059.articleprocessor.mapper; +import com.dre0059.articleprocessor.dto.DocumentContentDto; import com.dre0059.articleprocessor.dto.DocumentDto; import com.dre0059.articleprocessor.dto.SimpleDocumentDto; import com.dre0059.articleprocessor.model.Dokument; import java.util.List; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; @Mapper(componentModel = "spring") public interface DocumentMapper { + @Mapping(target = "publicationYear", source = "year") DocumentDto toDocumentDto(Dokument entity); - SimpleDocumentDto toSimpleDocument(Dokument entity); + + DocumentContentDto toDocumentContentDto(Dokument entity); + + SimpleDocumentDto toSimpleDocumentDto(Dokument entity); List<SimpleDocumentDto> toSimpleDocumentList(List<Dokument> entities); + + default String toString(byte[] bytes) { + if (bytes == null) { + return null; + } else { + return new String(bytes); + } + } + } diff --git a/src/main/java/com/dre0059/articleprocessor/model/Dokument.java b/src/main/java/com/dre0059/articleprocessor/model/Dokument.java index 1e6e8dd456530be3d8f176a941997d87778aa1c7..0969142429d23a7effdef4880ac1e1390cead349 100644 --- a/src/main/java/com/dre0059/articleprocessor/model/Dokument.java +++ b/src/main/java/com/dre0059/articleprocessor/model/Dokument.java @@ -1,12 +1,27 @@ package com.dre0059.articleprocessor.model; -import jakarta.persistence.*; -import org.hibernate.annotations.Cascade; - +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.Lob; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; import java.util.ArrayList; import java.util.List; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.Cascade; +@Setter +@Getter @Entity @Table(name = "documents") public class Dokument { @@ -26,14 +41,19 @@ public class Dokument { @JoinColumn(name = "category_id") private Category category; - // @Lob for huge text - //@Column(name = "abstractText", columnDefinition = "TEXT") - //private String abstractText; + @Lob + @Column + private byte[] abstractText; + + @Lob + @Column + private byte[] content; private String status; // if the value is PDF - the whole document was uploaded, otherwise the document was just mentioned in references private String publisher; private String target; // http link + @OneToMany(mappedBy = "fromDocument", cascade = CascadeType.ALL) private List<Reference> references = new ArrayList<>(); @@ -57,34 +77,7 @@ public class Dokument { this.status = status; } - public Long getId() { return id; } - public String getTitle() { return title; } - public Integer getYear() { return publicationYear; } - public String getDoi() { return doi; } - //public String getAbstractText() { return abstractText; } - public String getStatus() { return status; } - public String getPublisher() { return publisher; } - public List<Reference> getReferences() { return references; } - public List<Author> getAuthors() { return authors; } - - - public void setAuthors(List<Author> authors) { this.authors = authors; } - public void setTitle(String title) { this.title = title; } - public void setTarget(String target) { this.target = target; } - public void setPublicationYear(Integer publicationYear) { - this.publicationYear = publicationYear; - } - public void setDoi(String doi) { - this.doi = doi; - } - public void setStatus(String status) { - this.status = status; - } - public void setPublisher(String publisher) { - this.publisher = publisher; - } - public void setReferences(List<Reference> references) { - this.references = references; + public Integer getYear(){ + return publicationYear; } - public void setCategory(Category category) { this.category = category;} } diff --git a/src/main/java/com/dre0059/articleprocessor/repository/AuthorRepository.java b/src/main/java/com/dre0059/articleprocessor/repository/AuthorRepository.java index 913ab5bf0255c1e28efb934c50072a3d73559eb7..348dde743fdc0be9f9a15adb06a0e61abe765ba3 100644 --- a/src/main/java/com/dre0059/articleprocessor/repository/AuthorRepository.java +++ b/src/main/java/com/dre0059/articleprocessor/repository/AuthorRepository.java @@ -2,12 +2,8 @@ package com.dre0059.articleprocessor.repository; import com.dre0059.articleprocessor.model.Author; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; -import java.util.Optional; - @Repository public interface AuthorRepository extends JpaRepository<Author, Long> { /*@Query("SELECT CASE WHEN COUNT(a) > 0 THEN true ELSE false END FROM Author a WHERE a.lastName = :lastName AND a.firstName = :firstName") diff --git a/src/main/java/com/dre0059/articleprocessor/repository/DocumentRepository.java b/src/main/java/com/dre0059/articleprocessor/repository/DocumentRepository.java index 306c37f2d428a4eb84f14ddc52f719cc470a7271..84557ad5e69a9fe722093d3490d910eb819878a4 100644 --- a/src/main/java/com/dre0059/articleprocessor/repository/DocumentRepository.java +++ b/src/main/java/com/dre0059/articleprocessor/repository/DocumentRepository.java @@ -40,7 +40,7 @@ public interface DocumentRepository extends JpaRepository<Dokument, Long> { WHERE d.id = :id """ ) - List<Dokument> getReferencedDocumentsById(@Param("id") Long id); + List<Dokument> getReferencedDocumentsById(@Param("id") Long fromDocumentId); } diff --git a/src/main/java/com/dre0059/articleprocessor/service/DocumentService.java b/src/main/java/com/dre0059/articleprocessor/service/DocumentService.java index e32a09ddf7c885df6017be9c2024432a0da92f2f..fb9a2606c6f9e4dce1e3264847ad2c147a269c28 100644 --- a/src/main/java/com/dre0059/articleprocessor/service/DocumentService.java +++ b/src/main/java/com/dre0059/articleprocessor/service/DocumentService.java @@ -1,14 +1,17 @@ package com.dre0059.articleprocessor.service; +import com.dre0059.articleprocessor.dto.DocumentContentDto; import com.dre0059.articleprocessor.dto.DocumentDto; import com.dre0059.articleprocessor.dto.SimpleDocumentDto; import com.dre0059.articleprocessor.mapper.DocumentMapper; -import com.dre0059.articleprocessor.repository.*; -import com.dre0059.articleprocessor.model.*; - +import com.dre0059.articleprocessor.model.Author; +import com.dre0059.articleprocessor.model.Category; +import com.dre0059.articleprocessor.model.Dokument; +import com.dre0059.articleprocessor.repository.AuthorRepository; +import com.dre0059.articleprocessor.repository.CategoryRepository; +import com.dre0059.articleprocessor.repository.DocumentRepository; import jakarta.transaction.Transactional; import java.util.List; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service @@ -17,32 +20,40 @@ public class DocumentService { private final DocumentMapper documentMapper; private final DocumentRepository documentRepository; private final AuthorRepository authorRepository; + private final CategoryRepository categoryRepository; public DocumentService(DocumentMapper documentMapper, DocumentRepository documentRepository, - AuthorRepository authorRepository) { + AuthorRepository authorRepository, CategoryRepository categoryRepository) { this.documentMapper = documentMapper; this.documentRepository = documentRepository; this.authorRepository = authorRepository; + this.categoryRepository = categoryRepository; } @Transactional - public DocumentDto getDocumentById(Long id) { - return documentMapper.toDocumentDto(documentRepository.findById(id).orElse(null)); + public DocumentDto getDocumentById(Long documentId) { + Dokument dokument = documentRepository.findById(documentId).orElse(null); + + // PouĹľitie mappera na konverziu dokumentu do DTO + DocumentDto documentDto = documentMapper.toDocumentDto(dokument); + + return documentDto; } + @Transactional - public List<SimpleDocumentDto> getDocumentReferences(Long id) { - return documentMapper.toSimpleDocumentList(documentRepository.getReferencedDocumentsById(id)); + public DocumentContentDto getDocumentContentById(Long documentId) { + return documentMapper.toDocumentContentDto(documentRepository.findById(documentId).orElse(null)); } @Transactional - public List<SimpleDocumentDto> getAllReferences() { - return documentMapper.toSimpleDocumentList(documentRepository.findAll()); + public List<SimpleDocumentDto> getReferencedDocumentsById(Long documentId) { + return documentMapper.toSimpleDocumentList(documentRepository.getReferencedDocumentsById(documentId)); } @Transactional - public Dokument saveDocument(Dokument document) { - Dokument dok = new Dokument(); - return dok; + public List<SimpleDocumentDto> getAllDocuments() { + return documentMapper.toSimpleDocumentList(documentRepository.findAll()); } + } diff --git a/src/main/java/com/dre0059/articleprocessor/service/HeaderService.java b/src/main/java/com/dre0059/articleprocessor/service/HeaderService.java index 30fea4d56f6c13168c7d65ed11496cae487daac0..0a317b2f7686125bbb27483ed41b10e8dd9f4d66 100644 --- a/src/main/java/com/dre0059/articleprocessor/service/HeaderService.java +++ b/src/main/java/com/dre0059/articleprocessor/service/HeaderService.java @@ -1,18 +1,24 @@ package com.dre0059.articleprocessor.service; +import com.dre0059.articleprocessor.dto.CategoryDto; import com.dre0059.articleprocessor.model.Author; import com.dre0059.articleprocessor.model.Category; import com.dre0059.articleprocessor.model.Dokument; import com.dre0059.articleprocessor.repository.AuthorRepository; import com.dre0059.articleprocessor.repository.CategoryRepository; import com.dre0059.articleprocessor.repository.DocumentRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.swing.text.html.Option; -import java.util.*; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.commons.io.FileUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; // TODO : // 1. VALIDATE author based on surname and first INITIAL of the firstName. @@ -39,7 +45,6 @@ public class HeaderService { private List<Author> authorList = new ArrayList<>(); private String author; - private Category category; @Autowired public HeaderService(DocumentRepository documentRepository, AuthorRepository authorRepository, ReferenceService referenceService, CategoryRepository categoryRepository) { @@ -49,7 +54,7 @@ public class HeaderService { this.categoryRepository = categoryRepository; } - public void processHeader(String header, Optional<Category> category) { + public void processHeader(String header, String categoryId, File pdfFile) { this.title = this.parseHeaderFields(header, "title"); if(!this.parseHeaderFields(header, "doi").equals("Not found")){ @@ -79,22 +84,26 @@ public class HeaderService { System.out.println("Author list before checking duplicity: " + authorList); System.out.println("Author last names before checking duplicity: " + authorLastNames); - boolean headerDuplicity = documentRepository.existsByTitleAndAuthorsIn(title, authorLastNames); - // check duplicity of the document - if(headerDuplicity){ + if(documentRepository.existsByTitleAndAuthorsIn(title, authorLastNames)){ System.out.println("Document with this title and authors already exist"); return; } List<Author> savedAuthors = authorRepository.saveAll(authorList); Dokument dokument = new Dokument(title, year, doi, publisher, "PDF"); + Category category = categoryRepository.getReferenceById(categoryId); - //dokument.setCategory(category.get()); dokument.setAuthors(savedAuthors); System.out.println("Category: " + category); - category.ifPresent(dokument::setCategory); + dokument.setCategory(category); + + try { + dokument.setContent(FileUtils.readFileToByteArray(pdfFile)); + } catch (IOException e) { + System.err.println("Nepodarilo sa ulozit obsah suboru"); + } this.documentRepository.save(dokument); // output : Optional.empty diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index c1d0451d1f56081349e5f3f6817f189c022c577d..d2bd1712b948c3ac1f70b9254133413108b9300f 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -23,7 +23,7 @@ spring.application.name=articleProcessor #spring.jpa.show-sql=true #spring.datasource.url=jdbc:h2:mem:testdb -spring.datasource.url=jdbc:h2:file:/data/demo +spring.datasource.url=jdbc:h2:file:./data/demo spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password @@ -42,3 +42,5 @@ spring.thymeleaf.suffix=.html # Spring MVC for uploading PDF files spring.servlet.multipart.max-file-size=5MB spring.servlet.multipart.max-request-size=5MB + +grobid.host=http://158.196.98.65:8080 \ No newline at end of file diff --git a/src/main/resources/templates/upload.html b/src/main/resources/templates/upload.html index 6855121c27740746406aab1f1240ed6beed42271..dc4370fbc0f1b92fa0aa005a7290cf343e489f9d 100644 --- a/src/main/resources/templates/upload.html +++ b/src/main/resources/templates/upload.html @@ -1,93 +1,94 @@ <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> - <head> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <title>Upload PDF</title> - <script src = "https://code.jquery.com/jquery-3.6.0.min.js"></script> - <style> - #pdf-preview { - width: 500px; - height: 600px; - border: 1px solid #ddd; - margin-top: 10px; - } - </style> - </head> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Upload PDF</title> + <script src = "https://code.jquery.com/jquery-3.6.0.min.js"></script> + <link rel="stylesheet" th:href="@{/style.css}"> - <body> - <h1>Upload your PDF</h1> + <style> + #pdf-preview { + width: 500px; + height: 600px; + border: 1px solid #ddd; + margin-top: 10px; + } + </style> +</head> - <!-- formular na nahravanie PDF --> - <form action="/api/grobid/upload" method="post" id = "uploadForm" enctype = "multipart/form-data"> - <label for="fileInput">Choose PDF file:</label> - <input type = "file" id = "fileInput" name = "file" accept="application/pdf"> +<body> +<h1>Upload your PDF</h1> - <label for="category">Select Category:</label> +<!-- formular na nahravanie PDF --> +<form action="/api/grobid/upload" method="post" id = "uploadForm" enctype = "multipart/form-data"> + <label for="fileInput">Choose PDF file:</label> + <input type = "file" id = "fileInput" name = "file" accept="application/pdf"> - <select id="category" name="category" > - <option th:each="c : ${categories}" th:value="${c.getId()}" th:text ="${c.getId() + ' ' + c.getName()}"></option> - </select> + <label for="category">Select Category:</label> + <select id="category" name="category"> + <option th:each="c: ${categories}" th:value="${c.getId()}" th:text="${c.getName()}"></option> + </select> - <button type = "submit">Upload & Process the PDF</button> - </form> + <button type = "submit">Upload & Process the PDF</button> +</form> - <!-- zobrazenie PDF --> - <div id="pdf-container"> - <iframe id="pdf-preview" src="" style="display: none;"></iframe> - </div> +<!-- zobrazenie PDF --> +<div id="pdf-container"> + <iframe id="pdf-preview" src="" style="display: none;"></iframe> +</div> - <!-- JSON vĂ˝stup --> - <div id = "response-containter" style="display: none;"> - <h3>Response : </h3> - <pre id = "json-output"></pre> - </div> +<!-- JSON vĂ˝stup --> +<div id = "response-containter" style="display: none;"> + <h3>Response : </h3> + <pre id = "json-output"></pre> +</div> - <!--<a href="/api/document/22">click here</a> --> +<!--<a href="/api/document/22">click here</a> --> - <!-- .js na zobrazenie PDF --> - <script> - document.getElementById('fileInput').addEventListener('change', function(event){ - const file = event.target.files[0]; - if(file && file.type === 'application/pdf'){ - const fileURL = URL.createObjectURL(file); - document.getElementById('pdf-preview').src = fileURL; - document.getElementById('pdf-preview').style.display = 'block'; - } else { - alert ('Please, choose valid PDF file.'); - } - }); +<!-- .js na zobrazenie PDF --> +<script> + document.getElementById('fileInput').addEventListener('change', function(event){ + const file = event.target.files[0]; + if(file && file.type === 'application/pdf'){ + const fileURL = URL.createObjectURL(file); + document.getElementById('pdf-preview').src = fileURL; + document.getElementById('pdf-preview').style.display = 'block'; + } else { + alert ('Please, choose valid PDF file.'); + } + }); - // AJAX for sending a file - $('#uploadForm').submit(function(event) { - event.preventDefault(); - const fileInput = $('#fileInput')[0].files[0]; - const category = $('#category').val(); // ZĂskanie vybranej kategĂłrie + // AJAX for sending a file + $('#uploadForm').submit(function(event) { + event.preventDefault(); + const fileInput = $('#fileInput')[0].files[0]; + const category = $('#category').val(); // ZĂskanie vybranej kategĂłrie - if(!fileInput){ - alert("Please select a PDF file first."); - return; - } + if(!fileInput){ + alert("Please select a PDF file first."); + return; + } - const formData = new FormData(); - formData.append("file", fileInput); - formData.append("category", category); // Posielame aj kategĂłriu + const formData = new FormData(); + formData.append("file", fileInput); + formData.append("categoryId", category); // Posielame aj kategĂłriu - $.ajax({ - url: "/api/grobid/upload", - type : "POST", - data : formData, - processData : false, - contentType : false, - success : function(response){ - $('#json-output').text(JSON.stringify(response, null, 4)); - $('#response-containter').show(); - }, - error: function(){ - alert("Error processing PDF."); - } - }); - }); - </script> - </body> + $.ajax({ + url: "/api/upload", + type : "POST", + data : formData, + processData : false, + contentType : false, + success : function(response){ + $('#json-output').text(JSON.stringify(response, null, 4)); + $('#response-containter').show(); + }, + error: function(){ + alert("Error processing PDF."); + } + }); + }); +</script> +</body> </html> diff --git a/src/main/resources/templates/view-all.html b/src/main/resources/templates/view-all.html index 8715ea9fbcbd92d5e5368ec5f8a55e28e952785a..f19cadadef38dedc1f7166f172c7ca443c72043f 100644 --- a/src/main/resources/templates/view-all.html +++ b/src/main/resources/templates/view-all.html @@ -3,39 +3,37 @@ <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <title>Upload PDF</title> + <title>Article processor</title> + <link rel="stylesheet" th:href="@{/style.css}"> + <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <style> #pdf-preview { width: 500px; height: 600px; - border: 1px solid #ddd; + border: none; margin-top: 10px; } </style> </head> <body> -<h1>PDF files</h1> +<h1>Article processor</h1> -<!-- zobrazenie PDF --> -<div id="pdf-container"> - <iframe id="pdf-preview" src="" style="display: none;"></iframe> -</div> <table> <thead> <tr> <th>ID</th> <th>Title</th> - <th>Link</th> + <th>Status</th> </tr> </thead> <tbody> - <tr th:each="ref: ${references}"> - <td th:text="${ref.id}"></td> - <td th:text="${ref.title}"></td> - <td><a th:href="@{'/api/document/' + ${ref.id}}" th:text="${ref.title}"></a></td> + <tr th:each="doc: ${documents}"> + <td th:text="${doc.id}"></td> + <td><a th:href="@{'/view/' + ${doc.id}}" th:text="${doc.title}"></a></td> + <td th:text="${doc.status}"></td> </tr> </tbody> </table> diff --git a/src/main/resources/templates/view-pdf.html b/src/main/resources/templates/view-pdf.html index 8715ea9fbcbd92d5e5368ec5f8a55e28e952785a..175b5e68d3894a2a3d8fa716f168248769786dfa 100644 --- a/src/main/resources/templates/view-pdf.html +++ b/src/main/resources/templates/view-pdf.html @@ -3,42 +3,87 @@ <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <title>Upload PDF</title> - <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> + <title>View single PDF</title> + <!-- Bootstrap CSS --> + <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"> + <link rel="stylesheet" href="/style.css"> + <style> - #pdf-preview { - width: 500px; - height: 600px; - border: 1px solid #ddd; - margin-top: 10px; + body { + margin: 25px; + background: linear-gradient(black, black, gray); + color: white; + } + + a{ + text-decoration: none; + } + + /* RodiÄŤovskĂ˝ kontajner pre flexbox */ + #container { + display: flex; + justify-content: space-between; /* Rozdelenie priestoru medzi textom a PDF */ + align-items: flex-start; /* Zarovnanie na vrchnĂş ÄŤasĹĄ */ + gap: 20px; /* Medzera medzi textom a PDF */ + } + + /* Pre textovĂ© informácie a referencie */ + #text-container { + flex: 1; /* Text a referencie zabĂrajĂş všetok voÄľnĂ˝ priestor */ + padding : 20px; /* Trochu medzery medzi textom a PDF */ + } + + /* Pre PDF kontajner */ + #pdf-container { + width: 960px; /* Ĺ Ărka PDF kontajnera */ + height: 1500px; /* Výška PDF kontajnera */ } </style> </head> <body> -<h1>PDF files</h1> +<h1><a href="/view">All PDF files</a></h1> +<h2>Title : <span th:text="${docTitle}"></span> </h2> <!-- title aktuálneho dokumentu --> -<!-- zobrazenie PDF --> -<div id="pdf-container"> - <iframe id="pdf-preview" src="" style="display: none;"></iframe> -</div> +<div id="container"> + <!-- Textová sekcia --> + <div id="text-container"> + + <h3>Information about document </h3> + Category : <span> </span><br> + Author : <span> </span><br><br> + + Title : <span th:text="${docTitle}"></span><br> + Publication year : <span th:text="${year}"></span><br> + DOI : <span th:text="${doi}"></span><br> + Link : <span th:text="${link}"></span><br><br> -<table> - <thead> - <tr> - <th>ID</th> - <th>Title</th> - <th>Link</th> - </tr> - </thead> - <tbody> - <tr th:each="ref: ${references}"> - <td th:text="${ref.id}"></td> - <td th:text="${ref.title}"></td> - <td><a th:href="@{'/api/document/' + ${ref.id}}" th:text="${ref.title}"></a></td> - </tr> - </tbody> -</table> + <h2>References : </h2> + + <table> + <thead> + <tr> + <th>ID</th> + <th>Title</th> + <th>Status</th> + </tr> + </thead> + <tbody> + <tr th:each="ref: ${references}"> + <td th:text="${ref.id}"></td> + <!--<td th:text="${ref.title}"></td>--> + <td><a th:href="@{'/view/' + ${ref.id}}" th:text="${ref.title}"></a></td> + <td></td> + </tr> + </tbody> + </table> + </div> + + <!-- PDF sekcia --> + <div id="pdf-container"> + <embed th:src="@{'/api/documents/' + ${documentId} + '/content'}" type="application/pdf" width="960px" height="70%"/> + </div> +</div> </body> </html>