certificatecreator.CertificateCreator.java Source code

Java tutorial

Introduction

Here is the source code for certificatecreator.CertificateCreator.java

Source

/* 
 * Copyright 2016 Andrew Burch.
 *
 * This software is not available for distribution under any license.
 */
package certificatecreator;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Properties;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import static javafx.scene.control.OverrunStyle.LEADING_ELLIPSIS;
import javafx.scene.control.ScrollPane;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import javafx.scene.text.Text;
import javafx.stage.Modality;
import static javafx.scene.paint.Color.rgb;

public class CertificateCreator extends Application {

    String selectedStudent;
    String userPath;
    String resourcePath;

    @Override

    public void start(Stage primaryStage) {
        //Set class variables excluding selectedStudent.
        userPath = System.getProperty("user.dir");
        resourcePath = userPath + File.separator + "Resources";
        //Create resources folder if it does not exist.
        new File(resourcePath).mkdir();
        //Obtain properties from properties file or create a properties file if none exists.
        Properties properties = new Properties();
        establishProperties(properties);

        List<String> studentList = new ArrayList<>();
        //Create GUI.
        Scene scene = new Scene(createLayout(studentList, properties, primaryStage));
        scene.getStylesheets().add(CertificateCreator.class.getResource("Main.css").toExternalForm());
        primaryStage.setTitle("Certificate Creator");
        primaryStage.setResizable(false);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

    private String getDate() {
        //Obtains current date and formats it.

        DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.LONG);
        Calendar cal = Calendar.getInstance();
        String date = dateFormat.format(cal.getTime());
        return date;
    }

    private ListView<String> createVisibleStudentList(List<String> studentList, TextField studentField,
            Properties properties) {
        //Creates visible list for GUI

        //Create internal ObservableList based on studentList.
        ObservableList<String> observableStudentList = FXCollections.observableList(studentList);
        //Initialize uneditable list visible in GUI.
        ListView<String> visibleStudentList = new ListView<>();
        visibleStudentList.setEditable(false);
        //Initialize FilteredList whose items come from observableStudentList
        FilteredList<String> filteredItems = new FilteredList<String>(observableStudentList, p -> true);
        //Enable filtering of visibleStudentList based on entry in TextField studentField
        studentField.textProperty().addListener((obs, oldVal, newVal) -> {
            final String selected = visibleStudentList.getSelectionModel().getSelectedItem();
            Platform.runLater(() -> {
                filteredItems.setPredicate(boxListItem -> {
                    if (boxListItem.toUpperCase().startsWith(newVal.toUpperCase())) {
                        return true;
                    } else {
                        return false;
                    }
                });
            });
        });
        //As filteredItems updates, visibleStudentList does also.
        visibleStudentList.setItems(filteredItems);
        //Initiate certificate creation process upon click on list item.
        visibleStudentList.setOnMouseClicked((MouseEvent event) -> {
            selectedStudent = visibleStudentList.getSelectionModel().getSelectedItem();
            if (selectedStudent != null) {
                //Have user confirm certificate creation.
                Alert createCertificateAlert = new Alert(AlertType.CONFIRMATION,
                        "Create student certificate for " + selectedStudent + "?");
                createCertificateAlert.showAndWait().ifPresent(response -> {
                    if (response == ButtonType.OK) {
                        Path path = Paths.get(userPath + File.separator + selectedStudent + " Certificate.docx");
                        String tempPath = properties.getProperty("templatePath");
                        //Check if certificate already exists, warn user if so.
                        if (Files.exists(path)) {
                            Alert overwriteExistingAlert = new Alert(AlertType.WARNING,
                                    selectedStudent + " Certificate.docx exists. " + "Overwrite?");
                            overwriteExistingAlert.showAndWait().ifPresent(confirmOverwrite -> {
                                //Overwrite certificate if user confirms.      
                                if (confirmOverwrite == ButtonType.OK) {
                                    try {
                                        Files.deleteIfExists(path);
                                        createStudentCertificate(tempPath);
                                    } catch (IOException io) {
                                        System.err.println("Could not delete " + "existing certificate. New "
                                                + "certificate was not " + "generated. " + io);
                                    }
                                }
                            });
                        } else {
                            createStudentCertificate(tempPath);
                        }

                    }
                });

            }
        });
        return visibleStudentList;
    }

    private Label createStatusText(StringProperty inputTxt) {
        //Creates and binds TextProperties for GUI status messages.

        Label statusText = new Label();
        statusText.setId("statusText");
        statusText.textProperty().bind(inputTxt);
        return statusText;
    }

    private void extractStudentList(List<String> studentList, String stdntLstPath) {
        //extracts student list from text file.

        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(stdntLstPath)));
            String[] colNames = reader.readLine().split("\\t");
            int firstNameInd = 0;
            int lastNameInd = 0;
            for (int i = 0; i < colNames.length; i++) {
                if (colNames[i].matches("First Name")) {
                    firstNameInd = i;
                } else if (colNames[i].matches("Last Name")) {
                    lastNameInd = i;
                }
            }
            String str;
            int lines = 0;
            while ((str = reader.readLine()) != null) {
                String[] array = str.split("\\t");
                studentList.add(array[firstNameInd] + " " + array[lastNameInd]);
            }
            reader.close();
        } catch (IOException io) {
            System.err.println("I/O Exception in method extractStudentList: " + io);
            Alert studentListNotFound = new Alert(AlertType.WARNING,
                    "Specified student list was not found. " + "Please choose a different list.");
            studentListNotFound.showAndWait();
        } catch (NullPointerException npe) {
            System.err.println("Method copy failed:" + npe);
            Alert templateNotFound = new Alert(AlertType.WARNING,
                    "Specified student list was not found. " + "Please choose a different list.");
            templateNotFound.showAndWait();
        }
    }

    private void establishProperties(Properties properties) {
        //Retrieves properties or creates properties file if none exists.

        //define properties file path.
        Path propPath = Paths.get(resourcePath + File.separator + "data.properties");
        //If file does not exist, create it.
        if (Files.notExists(propPath)) {
            try {
                Files.createFile(propPath);
            } catch (IOException io) {
                System.err.println("Could not create properties file: " + io);
            }
            //Set property values to pass to created file.
            String studentListPath = "";
            String templatePath = "";
            properties.setProperty("studentListPath", studentListPath);
            properties.setProperty("templatePath", templatePath);
            //Write properties to created properties file.
            try (FileOutputStream writeProp = new FileOutputStream(
                    resourcePath + File.separator + "data.properties")) {
                properties.store(writeProp, null);
            } catch (IOException io) {
                System.err.println("Could not write properties to file: " + io);
            }
        } else {
            //Load properties from existing properties file.
            try {
                properties.load(new FileInputStream(propPath.toString()));
            } catch (IOException io) {
                System.err.println("Could not load properties: " + io);
            }
        }
    }

    private VBox createLayout(List<String> studentList, Properties properties, Stage primaryStage) {
        //Creates GUI elements and layout.

        //Create elements for studentList status text.
        String stdntLstPath = properties.getProperty("studentListPath");
        StringProperty stdntLstTxt = new SimpleStringProperty();
        Label listStatusText = createStatusText(stdntLstTxt);
        if (stdntLstPath.isEmpty()) {
            stdntLstTxt.set("No student list has been selected");
            listStatusText.setTextFill(rgb(255, 0, 0));
        } else {
            stdntLstTxt.set("Selected Student List:\n" + stdntLstPath);
            extractStudentList(studentList, stdntLstPath);
        }
        //Create elements for template status text.
        String templatePath = properties.getProperty("templatePath");
        StringProperty templateTxt = new SimpleStringProperty();
        Label tempStatusText = createStatusText(templateTxt);
        if (templatePath.isEmpty()) {
            templateTxt.set("No template has been selected");
            tempStatusText.setTextFill(rgb(255, 0, 0));
        } else {
            templateTxt.set("Selected template file:\n" + templatePath);
        }
        //Create elements for left half of GUI.
        Label stdntLbl = new Label("Student Name:");
        TextField stdntFld = new TextField();
        ListView<String> visibleStudentList = createVisibleStudentList(studentList, stdntFld, properties);
        Button setDirBtn = createDirectoryButton(properties, primaryStage);
        Button setTempBtn = createChooseTemplateButton(properties, templateTxt, tempStatusText, primaryStage);
        //Place elements in multiple VBoxes for positioning purposes.
        VBox studentName = new VBox();
        studentName.getChildren().add(stdntLbl);
        studentName.getChildren().add(stdntFld);
        VBox directoryInfo = new VBox();
        directoryInfo.setId("studentInfo");
        directoryInfo.getChildren().add(studentName);
        directoryInfo.getChildren().add(setDirBtn);
        directoryInfo.getChildren().add(listStatusText);
        listStatusText.setTextOverrun(LEADING_ELLIPSIS);
        VBox templateInfo = new VBox();
        templateInfo.setId("studentInfo");
        templateInfo.getChildren().add(setTempBtn);
        templateInfo.getChildren().add(tempStatusText);
        tempStatusText.setTextOverrun(LEADING_ELLIPSIS);
        VBox userInput = new VBox();
        userInput.setId("userInput");
        userInput.getChildren().add(directoryInfo);
        userInput.getChildren().add(templateInfo);
        VBox visibleStudents = new VBox();
        //Create elements for right half of GUI.
        Label studentListLbl = new Label("Student List:");
        visibleStudents.getChildren().add(studentListLbl);
        visibleStudents.getChildren().add(visibleStudentList);
        //Combine left and right halves of GUI in HBox.
        HBox content = new HBox();
        content.setId("content");
        content.getChildren().add(userInput);
        content.getChildren().add(visibleStudents);
        //Create MenuBar for access to readme file.
        MenuBar menuBar = new MenuBar();
        //Create File menu item.
        Menu menuFile = new Menu("File");
        //Create readme menu item under file.
        MenuItem readMeMenu = createReadMeMenuItem(primaryStage);
        menuFile.getItems().add(readMeMenu);
        //Create close menu item under readme
        MenuItem closeMenu = createCloseMenuItem();
        menuFile.getItems().add(closeMenu);
        //Add File menu to menuBar.
        menuBar.getMenus().add(menuFile);
        VBox layout = new VBox();
        layout.getChildren().add(menuBar);
        layout.getChildren().add(content);

        return layout;
    }

    private MenuItem createReadMeMenuItem(Stage primaryStage) {
        //Create menu item for readme.

        MenuItem readMeMenu = new MenuItem("ReadMe");
        //Make readme window open when menu item is clicked.
        readMeMenu.setOnAction((ActionEvent event) -> {
            final Stage readMeStage = new Stage();
            readMeStage.initModality(Modality.NONE);
            readMeStage.initOwner(primaryStage);
            readMeStage.setTitle("ReadMe");
            VBox dialogVbox = new VBox(20);
            //Read in text from readme source file.
            BufferedReader br = new BufferedReader(
                    new InputStreamReader(getClass().getResourceAsStream("readme.txt")));
            StringBuilder readMeLines = new StringBuilder();
            try {
                getText(readMeLines, br);
            } catch (IOException io) {
                System.err.println("Could not read readme file: " + io);
            }
            //Add text to readme window
            Text readMeContent = new Text(readMeLines.toString());
            readMeContent.setWrappingWidth(400);
            ScrollPane readMePane = new ScrollPane();
            readMePane.setContent(readMeContent);
            dialogVbox.getChildren().add(readMePane);
            Scene dialogScene = new Scene(dialogVbox, 420, 420);
            readMeStage.setScene(dialogScene);
            readMeStage.show();
        });
        return readMeMenu;
    }

    private MenuItem createCloseMenuItem() {
        //Create menu item to exit application.

        MenuItem closeMenu = new MenuItem("Close");
        closeMenu.setOnAction((ActionEvent event) -> {
            System.exit(0);
        });
        return closeMenu;
    }

    private Button createDirectoryButton(Properties properties, Stage primaryStage) {
        //Create button to choose student list directory.

        //Create button.
        Button dirBtn = new Button("Set Student List");
        dirBtn.setId("dirBtn");
        //Prompt user to choose student list file.
        FileChooser chooseList = new FileChooser();
        chooseList.setInitialDirectory(new File(resourcePath));
        chooseList.setTitle("Select Student List File");
        dirBtn.setOnAction((final ActionEvent a) -> {
            File listFile = chooseList.showOpenDialog(primaryStage);
            //Perform actions only if a new list is chosen.
            if (listFile != null) {
                //Modify properties file to reflect change in path of student list file.
                properties.setProperty("studentListPath", listFile.toString());
                try {
                    FileOutputStream saveProp = new FileOutputStream(
                            resourcePath + File.separator + "data.properties");
                    try {
                        properties.store(saveProp, null);
                    } catch (IOException io) {
                        System.err.println("Could not update properties: " + io);
                    }
                    restartApplication();
                } catch (FileNotFoundException fnf) {
                    System.err.println("Could not find save to properties file: " + fnf);
                }
            }
        });
        return dirBtn;
    }

    private Button createChooseTemplateButton(Properties properties, StringProperty templateTxt,
            Label tempStatusText, Stage primaryStage) {
        //Create button to choose certificate template.

        //Create button.
        Button chooseTemplateBtn = new Button("Set Certificate Template");
        chooseTemplateBtn.setId("chooseTemplateBtn");
        //Prompt user to choose a template file.
        FileChooser chooseTemplate = new FileChooser();
        chooseTemplate.setInitialDirectory(new File(resourcePath));
        chooseTemplate.setTitle("Select Certificate Template");
        chooseTemplateBtn.setOnAction((final ActionEvent a) -> {
            File templateFile = chooseTemplate.showOpenDialog(primaryStage);
            if (templateFile != null) {
                String tempPath = templateFile.toString();
                String extension = tempPath.substring(tempPath.lastIndexOf(".") + 1, tempPath.length());
                //Check if template is a .docx file. Abort and throw a warning if not.
                if ("docx".equals(extension)) {
                    properties.setProperty("templatePath", templateFile.toString());
                    templateTxt.set("Selected template file:\n" + templateFile.toString());
                    tempStatusText.setTextFill(rgb(0, 0, 0));
                    try {
                        FileOutputStream saveProp = new FileOutputStream(
                                resourcePath + File.separator + "data.properties");
                        try {
                            properties.store(saveProp, null);
                        } catch (IOException io) {
                            System.err.println("Could not update properties: " + io);
                        }
                    } catch (FileNotFoundException fnf) {
                        System.err.println("Could not create output stream to " + "properties file: " + fnf);
                    }
                } else {
                    Alert badTypeAlert = new Alert(AlertType.WARNING,
                            "Selected certificate file is not " + "of proper format. Please choose another file "
                                    + "or consult ReadMe for more information.");
                    badTypeAlert.showAndWait();
                }
            }
        });
        return chooseTemplateBtn;
    }

    private void createStudentCertificate(String tempPath) {
        //Creates student certificate.
        //Read in template file and define output file.
        File inFile = new File(tempPath);
        File outFile = new File(userPath + File.separator + selectedStudent + "Certificate.docx");
        //Create output file. Throw alert if tempPath references nonexisting file.
        try {
            copy(inFile, outFile);
            //Create internal word document based on copied template file. Write content.
            try {
                XWPFDocument certificate = new XWPFDocument(new FileInputStream(outFile));
                XWPFParagraph p1 = certificate.createParagraph();
                p1.setAlignment(ParagraphAlignment.CENTER);
                XWPFRun r1 = p1.createRun();
                r1.setFontFamily("Candara");
                r1.setFontSize(40);
                r1.addBreak();
                r1.setText("Lawton Elementary Congratulates");
                XWPFRun r2 = p1.createRun();
                r2.setFontFamily("Candara");
                r2.setFontSize(36);
                r2.setBold(true);
                r2.addBreak();
                r2.addBreak();
                r2.setText(selectedStudent);
                r2.addBreak();
                r2.addBreak();
                XWPFRun r3 = p1.createRun();
                r3.setFontFamily("Candara");
                r3.setFontSize(26);
                r3.setText("For being a Lawton CARES winner on");
                r3.addBreak();
                String date = getDate();
                r3.setText(date);
                r3.addBreak();
                r3.addBreak();
                r3.addBreak();
                r3.addBreak();
                XWPFRun r4 = p1.createRun();
                r4.setColor("5B9BD5");
                r4.setFontFamily("Candara");
                r4.setFontSize(26);
                r4.setText("Compassion+Attitude+Respect+Effort+Safety=CARES");
                //Write internal document to copied templated file.
                try {
                    FileOutputStream out = new FileOutputStream(outFile.toString());
                    try {
                        certificate.write(out);
                        out.close();
                    } catch (IOException io) {
                        System.err.println("Could not write file: " + io);
                    }
                } catch (FileNotFoundException fnf) {
                    System.err.println("Could not find output file: " + fnf);
                }
            } catch (IOException io) {
                System.err.println("Copy of template could not be found: " + io);
            }
        } catch (IOException io) {
            System.err.println("Method copy failed:" + io);
        } catch (NullPointerException npe) {
            System.err.println("Method copy failed:" + npe);
            Alert templateNotFound = new Alert(AlertType.WARNING,
                    "Specified certificate template was not found. " + "Please choose a different template.");
            templateNotFound.showAndWait();
        }
    }

    private void getText(StringBuilder readMeLines, BufferedReader br) throws IOException {
        //Retrieves content from readme file.

        int i = 0;
        String line = "";

        while (line != null) {
            readMeLines.append(line).append("\n");
            line = br.readLine();
        }
    }

    private static void copy(File source, File target) throws IOException, NullPointerException {
        //Copies template file to student certificate.

        FileChannel sourceChannel = null;
        FileChannel targetChannel = null;
        try {
            sourceChannel = new FileInputStream(source).getChannel();
            targetChannel = new FileOutputStream(target).getChannel();
            targetChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
        } finally {
            targetChannel.close();
            sourceChannel.close();
        }
    }

    private void restartApplication() {
        //Restarts application

        final String javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
        try {
            final File currentJar = new File(
                    CertificateCreator.class.getProtectionDomain().getCodeSource().getLocation().toURI());
            if (!currentJar.getName().endsWith(".jar"))
                return;
            final ArrayList<String> command = new ArrayList<>();
            command.add(javaBin);
            command.add("-jar");
            command.add(currentJar.getPath());
            final ProcessBuilder builder = new ProcessBuilder(command);
            try {
                builder.start();
            } catch (IOException io) {
                System.err.println("I/O exception, program could not be " + "restarted." + io);
            }
            System.exit(0);
        } catch (URISyntaxException uri) {
            System.err.println("URI syntax exception: " + uri);
        }
    }
}