diff --git a/pom.xml b/pom.xml index 5a5a744f094003afa4cf32b130e7d276ade41c58..e1dbe4ac8be3f13637437c7110c65f9e3c676074 100644 --- a/pom.xml +++ b/pom.xml @@ -114,6 +114,20 @@ <scope>test</scope> <version>1.4.194</version> </dependency> + + <!-- Pdf --> + <dependency> + <groupId>com.itextpdf</groupId> + <artifactId>itextpdf</artifactId> + <version>5.5.10</version> + </dependency> + + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcprov-jdk15on</artifactId> + <version>1.56</version> + </dependency> + </dependencies> <build> <plugins> diff --git a/src/main/java/NTNU/IDATT1002/App.java b/src/main/java/NTNU/IDATT1002/App.java index 7ab7324377bc9362cbc05e14b00b6293a6d125e1..bb4ba2a59ac6b4ee5648c36d5ee3539742083ff9 100644 --- a/src/main/java/NTNU/IDATT1002/App.java +++ b/src/main/java/NTNU/IDATT1002/App.java @@ -1,17 +1,12 @@ package NTNU.IDATT1002; import NTNU.IDATT1002.controllers.DataExchange; -import NTNU.IDATT1002.repository.LoginRepository; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; -import org.slf4j.Logger; -import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; -import javax.persistence.Persistence; import java.io.IOException; @@ -20,8 +15,6 @@ public class App extends Application { public static DataExchange ex; private static Scene scene; - private static Logger log; - @Override public void start(Stage stage) throws IOException { ex = new DataExchange(); diff --git a/src/main/java/NTNU/IDATT1002/models/Image.java b/src/main/java/NTNU/IDATT1002/models/Image.java index 98082fdd946e697ea7c5ae730023b583eb2b4b6b..db104fb66487b5c739bc00d6c46a1f1b9c83f06b 100644 --- a/src/main/java/NTNU/IDATT1002/models/Image.java +++ b/src/main/java/NTNU/IDATT1002/models/Image.java @@ -101,7 +101,6 @@ public class Image { * @param imageAlbum the image album to add to */ public void addImageAlbum(ImageAlbum imageAlbum) { - imageAlbum.addImage(this); imageAlbums.add(imageAlbum); } @@ -111,7 +110,6 @@ public class Image { * @param imageAlbum the image album to remove from */ public void removeImageAlbum(ImageAlbum imageAlbum) { - imageAlbum.removeImage(this); imageAlbums.remove(imageAlbum); } diff --git a/src/main/java/NTNU/IDATT1002/models/ImageAlbum.java b/src/main/java/NTNU/IDATT1002/models/ImageAlbum.java index 0e5d4998f6c8a56d064655a95998c7eeef1bfafe..8607b3448154adc7dade24062a54c172acba0463 100644 --- a/src/main/java/NTNU/IDATT1002/models/ImageAlbum.java +++ b/src/main/java/NTNU/IDATT1002/models/ImageAlbum.java @@ -56,48 +56,60 @@ public class ImageAlbum { this.id = id; } - public void setTitle(String title) { - this.title = title; - } - - public void setDescription(String description) { - this.description = description; + public Long getId() { + return id; } - public void setUser(User user) { - this.user = user; + public String getTitle() { + return title; } - public void setTags(List<Tag> tags) { - this.tags = tags; + public User getUser() { + return user; } - public void setImages(List<Image> images) { - this.images = images; + public List<Image> getImages() { + return images; } - public Long getId() { - return id; + public String getDescription() { + return description; } - public String getTitle() { - return title; + public Date getCreatedAt() { + return createdAt; } - public User getUser() { - return user; + public Date getUpdatedAt() { + return updatedAt; } public List<Tag> getTags() { return tags; } - public String getDescription() { - return description; + public void setTitle(String title) { + this.title = title; } - public List<Image> getImages() { - return images; + public void setDescription(String description) { + this.description = description; + } + + public void setUser(User user) { + this.user = user; + } + + public void setTags(List<Tag> tags) { + this.tags = tags; + } + + public void setImages(List<Image> images) { + this.images = images; + } + + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; } /** diff --git a/src/main/java/NTNU/IDATT1002/utils/CreateUser.java b/src/main/java/NTNU/IDATT1002/utils/CreateUser.java deleted file mode 100644 index e546a6bfda341c0f7fe1a79fa1d97ecfafc6506c..0000000000000000000000000000000000000000 --- a/src/main/java/NTNU/IDATT1002/utils/CreateUser.java +++ /dev/null @@ -1,7 +0,0 @@ -package NTNU.IDATT1002.utils; - - -public class CreateUser { - - -} diff --git a/src/main/java/NTNU/IDATT1002/utils/ImageUtil.java b/src/main/java/NTNU/IDATT1002/utils/ImageUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..96d8dacf1b1efb857cf8694cb880ad047368f0f6 --- /dev/null +++ b/src/main/java/NTNU/IDATT1002/utils/ImageUtil.java @@ -0,0 +1,22 @@ +package NTNU.IDATT1002.utils; + +import java.io.File; +import java.io.FileInputStream; + +public class ImageUtil { + + public static byte[] convertToBytes(String path) { + File file = new File(path); + byte[] byteFile = new byte[(int) file.length()]; + + try { + FileInputStream fileInputStream = new FileInputStream(file); + fileInputStream.read(byteFile); + fileInputStream.close(); + } catch (Exception e) { + e.printStackTrace(); + } + + return byteFile; + } +} diff --git a/src/main/java/NTNU/IDATT1002/utils/PdfDocument.java b/src/main/java/NTNU/IDATT1002/utils/PdfDocument.java new file mode 100644 index 0000000000000000000000000000000000000000..56d664426cea672e48582e34556df02749d41e44 --- /dev/null +++ b/src/main/java/NTNU/IDATT1002/utils/PdfDocument.java @@ -0,0 +1,252 @@ +package NTNU.IDATT1002.utils; + +import NTNU.IDATT1002.models.Image; +import NTNU.IDATT1002.models.ImageAlbum; +import NTNU.IDATT1002.models.Metadata; +import com.itextpdf.text.*; +import com.itextpdf.text.pdf.PdfWriter; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Date; + + +/** + * Class PdfDocument. Generates a pdf document displaying a given image album. + * + * @author Eirik Steira + * @version 1.0 22.03.20 + */ +public class PdfDocument { + + /** + * Height ratio satisfying a 16:9 ratio. + */ + private final double HEIGHT_RATIO = 5.3; + + private ImageAlbum imageAlbum; + + private Document document; + + private String DESTINATION_FILE; + + private String defaultTitle = "Album"; + + /** + * Standard fonts. + */ + private Font headerFont = new Font(Font.FontFamily.TIMES_ROMAN, 18, + Font.BOLD); + private Font subFont = new Font(Font.FontFamily.TIMES_ROMAN, 16, + Font.BOLD); + private Font smallFont = new Font(Font.FontFamily.TIMES_ROMAN, 12); + + public PdfDocument(ImageAlbum imageAlbum, String DESTINATION_FILE) { + this.imageAlbum = imageAlbum; + this.DESTINATION_FILE = DESTINATION_FILE; + this.document = new Document(); + } + + /** + * Create a new pdf document. + */ + public void createPdfDocument() { + try { + generatePdfDocument(); + } catch (IOException | DocumentException e) { + e.printStackTrace(); + } + } + + /** + * Try to generate a pdf document. + * + * @throws IOException + * @throws DocumentException + */ + private void generatePdfDocument() throws IOException, DocumentException { + PdfWriter.getInstance(document, new FileOutputStream(DESTINATION_FILE)); + document.open(); + + addHeadlines(); + addContent(); + + document.close(); + } + + /** + * Add default headlines to the document, ie document title, ownership and date. + * + * @throws DocumentException + */ + private void addHeadlines() throws DocumentException { + Paragraph headline = new Paragraph(); + + addEmptyLineTo(headline, 1); + + headline.add(new Paragraph(defaultTitle, headerFont)); + addEmptyLineTo(headline, 1); + + headline.add(new Paragraph( + "Generated by: " + imageAlbum.getUser().getUsername() + ", " + + new Date(), + smallFont)); + addEmptyLineTo(headline, 2); + + document.add(headline); + } + + /** + * Add main content to the document. This entails image album meta and all images. + * + * @throws DocumentException + * @throws IOException + */ + private void addContent() throws DocumentException, IOException { + addImageAlbumMeta(); + addImagesContainer(); + } + + /** + * Add image album meta to the document, such as title, user etc. + * + * @throws DocumentException + */ + private void addImageAlbumMeta() throws DocumentException { + Paragraph imageAlbumMeta = new Paragraph(); + String imageAlbumMetaContent = formatImageAlbumMeta(); + imageAlbumMeta.add(new Paragraph( + imageAlbumMetaContent, + smallFont)); + + addEmptyLineTo(imageAlbumMeta, 1); + document.add(imageAlbumMeta); + } + + /** + * Add container to contain images and a headline. + * + * @throws DocumentException + * @throws IOException + */ + private void addImagesContainer() throws DocumentException, IOException { + Paragraph imagesContainer = new Paragraph(); + + imagesContainer.add(new Paragraph("Images:", subFont)); + document.add(imagesContainer); + addAllImages(); + } + + /** + * Add all images in the album to the document. + * + * @throws IOException + * @throws DocumentException + */ + private void addAllImages() throws IOException, DocumentException { + for (Image image : imageAlbum.getImages()) + addSingleImage(image); + } + + /** + * Add a single image to the document. + * + * @param image the image to add. + * @throws IOException + * @throws DocumentException + */ + private void addSingleImage(Image image) throws IOException, DocumentException { + com.itextpdf.text.Image displayImage = getImageFileFromBytes(image.getRawImage()); + scaleImage(displayImage); + + document.add(displayImage); + addImageMetaData(image); + } + + /** + * Convert an array of bytes to {@link com.itextpdf.text.Image}. + * + * @param imageBytes the array of bytes to convert + * @return the image to display + * @throws IOException + * @throws BadElementException + */ + private com.itextpdf.text.Image getImageFileFromBytes(byte[] imageBytes) + throws IOException, BadElementException { + return com.itextpdf.text.Image.getInstance(imageBytes); + } + + /** + * Scale given {@link com.itextpdf.text.Image image} to stretch + * half the width of the page, remaining a 16:9 ratio. + * + * @param image the image to scale + */ + private void scaleImage(com.itextpdf.text.Image image) { + float documentWidth = PageSize.A4.getWidth() - 2 * PageSize.A4.getBorder(); + float scaledHeight = (float) (documentWidth / 2 * HEIGHT_RATIO); + + image.scaleToFit(documentWidth / 2, scaledHeight); + } + + /** + * Add an images metadata to the document. + * + * @param image the image holding the metadata + * @throws DocumentException + */ + private void addImageMetaData(Image image) throws DocumentException { + Metadata metadata = image.getMetadata(); + if (metadata != null) + document.add(new Paragraph(metadata.toString())); + } + + /** + * Format the album meta. + * + * @return the formatted album + */ + private String formatImageAlbumMeta() { + return new StringBuilder() + .append("Title: ") + .append(imageAlbum.getTitle()) + .append("\n") + .append("User: ") + .append(imageAlbum.getUser().getUsername()) + .append("\n") + .append("Created at: ") + .append(imageAlbum.getCreatedAt()) + .append("\n") + .append("Description: ") + .append(imageAlbum.getDescription()) + .append("\n") + .append("Tags: ") + .append(formatTags()) + .toString(); + } + + /** + * Format the albums tags, separated by a comma. + * + * @return the formatted tags + */ + private String formatTags() { + StringBuilder tags = new StringBuilder(); + imageAlbum.getTags().forEach(tag -> tags.append(tag.getName()).append(", ")); + + return tags.toString(); + } + + /** + * Add an empty line to the document. + * + * @param paragraph the paragraph to insert an empty line into + * @param number the number of empty lines desired + */ + private void addEmptyLineTo(Paragraph paragraph, int number) { + for (int i = 0; i < number; i++) { + paragraph.add(new Paragraph(" ")); + } + } + +} diff --git a/src/test/java/NTNU/IDATT1002/utils/PdfDocumentTest.java b/src/test/java/NTNU/IDATT1002/utils/PdfDocumentTest.java new file mode 100644 index 0000000000000000000000000000000000000000..54bbfdaad68bb33c25ce0d97f585abca1552208a --- /dev/null +++ b/src/test/java/NTNU/IDATT1002/utils/PdfDocumentTest.java @@ -0,0 +1,77 @@ +package NTNU.IDATT1002.utils; + +import NTNU.IDATT1002.models.Image; +import NTNU.IDATT1002.models.ImageAlbum; +import NTNU.IDATT1002.models.User; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.Date; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + + +/** + * Class PdfDocumentTest to test the generation of pdf documents. + */ +class PdfDocumentTest { + + private static final String PATH_TO_PDF = "src/test/java/tmp/generatedImageAlbumPdf.pdf"; + + private static final String PATH_SEPARATOR = File.pathSeparator; + + private ImageAlbum imageAlbum; + + private Image image; + + private User user; + + /** + * Setup an image album with a user and two images. + */ + @BeforeEach + public void setup() { + byte[] byteFile = ImageUtil.convertToBytes("src/test/java/tmp/test_image_1.jpg"); + image = new Image(); + image.setRawImage(byteFile); + + user = new User(); + user.setUsername("Alex Johnson"); + + imageAlbum = new ImageAlbum(); + imageAlbum.setTitle("Test Title"); + imageAlbum.setUser(user); + imageAlbum.setDescription("This is a test."); + imageAlbum.setCreatedAt(new Date()); + imageAlbum.addImage(image); + + byteFile = ImageUtil.convertToBytes("src/test/java/tmp/test_image_2.jpg"); + image = new Image(); + image.setRawImage(byteFile); + imageAlbum.addImage(image); + } + + /** + * Delete the generated pdf after all tests have been executed. + */ + @AfterAll + public static void tearDown() { + File file = new File(PATH_TO_PDF); + file.delete(); + } + + /** + * Test that a pdf document is successfully created. + */ + @Test + void testCreatePdfDocumentCreatesPdfDocument() { + PdfDocument document = new PdfDocument(imageAlbum, PATH_TO_PDF); + document.createPdfDocument(); + + assertNotNull(document); + } + + +} \ No newline at end of file diff --git a/src/test/java/tmp/test_image_1.jpg b/src/test/java/tmp/test_image_1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b0e20dcf03e505e252385013c302b859b5f44286 Binary files /dev/null and b/src/test/java/tmp/test_image_1.jpg differ diff --git a/src/test/java/tmp/test_image_2.jpg b/src/test/java/tmp/test_image_2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6315a79e35f8dd280aadcc2fbbe3b98e8f6f9c81 Binary files /dev/null and b/src/test/java/tmp/test_image_2.jpg differ