From eb0e70a3841af6ba381c48cd13cf0ae6b67e570a Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Fri, 24 Aug 2018 16:31:44 +0200 Subject: [PATCH] Added styled messages. --- src/main/java/nl/andrewlalis/Main.java | 56 ++++------ .../java/nl/andrewlalis/model/Storable.java | 18 ---- .../andrewlalis/model/database/Database.java | 28 ++++- .../ui/control/CommandExecutor.java | 10 ++ .../ui/control/CommandFieldKeyListener.java | 24 +++++ .../ui/control/OutputTextHandler.java | 42 ++++++++ .../andrewlalis/ui/view/InitializerApp.java | 102 ++++++++++++++++++ .../andrewlalis/ui/view/OutputTextPane.java | 83 ++++++++++++++ .../java/nl/andrewlalis/util/FileUtils.java | 31 ++++++ .../java/nl/andrewlalis/util/Logging.java | 8 +- 10 files changed, 345 insertions(+), 57 deletions(-) delete mode 100644 src/main/java/nl/andrewlalis/model/Storable.java create mode 100644 src/main/java/nl/andrewlalis/ui/control/CommandExecutor.java create mode 100644 src/main/java/nl/andrewlalis/ui/control/CommandFieldKeyListener.java create mode 100644 src/main/java/nl/andrewlalis/ui/control/OutputTextHandler.java create mode 100644 src/main/java/nl/andrewlalis/ui/view/InitializerApp.java create mode 100644 src/main/java/nl/andrewlalis/ui/view/OutputTextPane.java diff --git a/src/main/java/nl/andrewlalis/Main.java b/src/main/java/nl/andrewlalis/Main.java index f00ca3c..3545fe7 100644 --- a/src/main/java/nl/andrewlalis/Main.java +++ b/src/main/java/nl/andrewlalis/Main.java @@ -4,10 +4,12 @@ import nl.andrewlalis.model.database.Database; import nl.andrewlalis.git_api.GithubManager; import nl.andrewlalis.model.Student; import nl.andrewlalis.model.StudentTeam; +import nl.andrewlalis.ui.view.InitializerApp; import nl.andrewlalis.util.CommandLine; import nl.andrewlalis.util.Logging; import nl.andrewlalis.util.TeamGenerator; +import javax.swing.*; import java.io.IOException; import java.util.List; import java.util.Map; @@ -34,18 +36,21 @@ public class Main { logger.severe("Unable to save log to file."); } + // Initialize User Interface. + InitializerApp app = new InitializerApp(); + logger.info("GithubManager for Github Repositories in Educational Organizations."); // Get studentTeams from CSV file. - List studentTeams = getStudentTeamsFromCSV(userOptions.get("input"), Integer.parseInt(userOptions.get("teamsize"))); - - GithubManager githubManager = new GithubManager( - userOptions.get("organization"), - userOptions.get("token"), - "assignments_2018", - "teaching-assistants", - "advoop_2018" - ); +// List studentTeams = getStudentTeamsFromCSV(userOptions.get("input"), Integer.parseInt(userOptions.get("teamsize"))); +// +// GithubManager githubManager = new GithubManager( +// userOptions.get("organization"), +// userOptions.get("token"), +// "assignments_2018", +// "teaching-assistants", +// "advoop_2018" +// ); try { //githubManager.initializeGithubRepos(studentTeams); @@ -55,34 +60,17 @@ public class Main { } // Initialize database. - Database db = new Database("database/initializer.sqlite"); - db.initialize(); - for (StudentTeam team : studentTeams) { - for (Student student : team.getStudents()) { - db.storeStudent(student); - } - } +// Database db = new Database("database/initializer.sqlite"); +// db.initialize(); +// for (StudentTeam team : studentTeams) { +// for (Student student : team.getStudents()) { +// db.storeStudent(student); +// } +// } } - /** - * Reads a list of students from a CSV file and compiles a list of teams based on their preferred partners. - * @param filename The name of the CSV file. - * @param teamSize The intended size of teams. - * @return A list of student teams. - */ - private static List getStudentTeamsFromCSV(String filename, int teamSize) { - List studentTeams = null; - try { - studentTeams = TeamGenerator.generateFromCSV(filename, teamSize); - logger.fine("Teams created:\n" + studentTeams); - return studentTeams; - } catch (IOException | ArrayIndexOutOfBoundsException e) { - logger.severe("Unable to generate studentTeams from CSV file, exiting."); - System.exit(1); - return null; - } - } + } diff --git a/src/main/java/nl/andrewlalis/model/Storable.java b/src/main/java/nl/andrewlalis/model/Storable.java deleted file mode 100644 index 29a485e..0000000 --- a/src/main/java/nl/andrewlalis/model/Storable.java +++ /dev/null @@ -1,18 +0,0 @@ -package nl.andrewlalis.model; - -import java.sql.Connection; - -/** - * Defines objects which may be stored in the database, and requires that they implement methods for both storage and - * retrieval of the objects. - */ -public interface Storable { - - /** - * Stores the object in the database. - * @param connection The connection to the database which can be used for preparation of and execution of queries. - * @return True if the object is successfully stored, false if an error occurred. - */ - boolean store(Connection connection); - -} diff --git a/src/main/java/nl/andrewlalis/model/database/Database.java b/src/main/java/nl/andrewlalis/model/database/Database.java index c4da185..33fb282 100644 --- a/src/main/java/nl/andrewlalis/model/database/Database.java +++ b/src/main/java/nl/andrewlalis/model/database/Database.java @@ -3,6 +3,7 @@ package nl.andrewlalis.model.database; import nl.andrewlalis.model.Person; import nl.andrewlalis.model.Student; import nl.andrewlalis.model.TeachingAssistant; +import nl.andrewlalis.model.Team; import java.sql.*; import java.util.List; @@ -85,6 +86,7 @@ public class Database { */ private boolean storePerson(Person person, int personType) { try { + logger.finest("Storing person: " + person); String sql = "INSERT INTO persons (id, name, email_address, github_username, person_type_id) VALUES (?, ?, ?, ?, ?);"; PreparedStatement stmt = this.connection.prepareStatement(sql); stmt.setInt(1, person.getNumber()); @@ -92,9 +94,10 @@ public class Database { stmt.setString(3, person.getEmailAddress()); stmt.setString(4, person.getGithubUsername()); stmt.setInt(5, personType); - return stmt.execute(); + stmt.execute(); + return true; } catch (SQLException e) { - e.printStackTrace(); + logger.severe("SQLException while inserting Person: " + person + '\n' + e.getMessage()); return false; } } @@ -131,6 +134,26 @@ public class Database { } } + /** + * Stores a team in the database. + * @param team The team to store. + * @param type The type of team that this is. + * @return True if successful, false otherwise. + */ + public boolean storeTeam(Team team, int type) { + try { + String sql = "INSERT INTO teams (id, team_type_id) VALUES (?, ?);"; + PreparedStatement stmt = this.connection.prepareStatement(sql); + stmt.setInt(1, team.getId()); + stmt.setInt(2, type); + stmt.execute(); + return true; + } catch (SQLException e) { + logger.severe("SQLException while inserting team: " + team + '\n' + e.getMessage()); + return false; + } + } + /** * Stores a student without a team. * @param student The student to store. @@ -147,6 +170,7 @@ public class Database { * @return True if the operation was successful, false otherwise. */ public boolean storeStudent(Student student, int teamId) { + logger.finest("Storing student: " + student); if (!storePerson(student, PERSON_TYPE_STUDENT)) { return false; } diff --git a/src/main/java/nl/andrewlalis/ui/control/CommandExecutor.java b/src/main/java/nl/andrewlalis/ui/control/CommandExecutor.java new file mode 100644 index 0000000..2d52f50 --- /dev/null +++ b/src/main/java/nl/andrewlalis/ui/control/CommandExecutor.java @@ -0,0 +1,10 @@ +package nl.andrewlalis.ui.control; + +/** + * Manages parsing an entered string and executing a task based upon information in the command. + */ +public class CommandExecutor { + + + +} diff --git a/src/main/java/nl/andrewlalis/ui/control/CommandFieldKeyListener.java b/src/main/java/nl/andrewlalis/ui/control/CommandFieldKeyListener.java new file mode 100644 index 0000000..f0b170f --- /dev/null +++ b/src/main/java/nl/andrewlalis/ui/control/CommandFieldKeyListener.java @@ -0,0 +1,24 @@ +package nl.andrewlalis.ui.control; + +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; + +public class CommandFieldKeyListener implements KeyListener { + + @Override + public void keyTyped(KeyEvent keyEvent) { + + } + + @Override + public void keyPressed(KeyEvent keyEvent) { + + } + + @Override + public void keyReleased(KeyEvent keyEvent) { + if (keyEvent.getKeyCode() == KeyEvent.VK_ENTER) { + System.out.println("Enter pressed."); + } + } +} diff --git a/src/main/java/nl/andrewlalis/ui/control/OutputTextHandler.java b/src/main/java/nl/andrewlalis/ui/control/OutputTextHandler.java new file mode 100644 index 0000000..a4d6710 --- /dev/null +++ b/src/main/java/nl/andrewlalis/ui/control/OutputTextHandler.java @@ -0,0 +1,42 @@ +package nl.andrewlalis.ui.control; + +import nl.andrewlalis.ui.view.OutputTextPane; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.logging.Handler; +import java.util.logging.LogRecord; + +public class OutputTextHandler extends Handler { + + /** + * The pane to which this handler writes. + */ + private OutputTextPane outputPane; + + public OutputTextHandler(OutputTextPane outputPane) { + this.outputPane = outputPane; + } + + @Override + public void publish(LogRecord logRecord) { + DateFormat df = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss"); + String dateString = df.format(new Date(logRecord.getMillis())); + String sourceLocationString = logRecord.getSourceClassName() + "::" + logRecord.getSourceMethodName(); + this.outputPane.printStyled(dateString + ' ', "gray_italics"); + this.outputPane.printStyled(logRecord.getLevel().getName() + ": ", "bold"); + this.outputPane.printStyled(sourceLocationString + "\n\t", "bold"); + this.outputPane.printStyled(logRecord.getMessage() + '\n', "smaller"); + } + + @Override + public void flush() { + + } + + @Override + public void close() throws SecurityException { + + } +} diff --git a/src/main/java/nl/andrewlalis/ui/view/InitializerApp.java b/src/main/java/nl/andrewlalis/ui/view/InitializerApp.java new file mode 100644 index 0000000..3eef11f --- /dev/null +++ b/src/main/java/nl/andrewlalis/ui/view/InitializerApp.java @@ -0,0 +1,102 @@ +package nl.andrewlalis.ui.view; + +import nl.andrewlalis.ui.control.CommandFieldKeyListener; +import nl.andrewlalis.ui.control.OutputTextHandler; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.util.logging.Logger; + +/** + * Represents the main user interface element that is referenced in main to construct the graphic interface. + */ +public class InitializerApp extends JFrame { + + /** + * The window title. + */ + private static final String FRAME_TITLE = "Github Initializer"; + + /** + * A default size of the window on startup. + */ + private static final Dimension SIZE = new Dimension(800, 600); + + private OutputTextPane outputTextPane; + + public InitializerApp() { + this.initFrame(); + } + + public void printMessage() { + + } + + /** + * Initializes the handler which passes logging information to the text pane for display. + */ + private void initLoggingHandler() { + Logger logger = Logger.getGlobal(); + logger.addHandler(new OutputTextHandler(this.outputTextPane)); + } + + /** + * Initializes the frame before display should begin. + */ + private void initFrame() { + this.setTitle(FRAME_TITLE); + this.setDefaultCloseOperation(DISPOSE_ON_CLOSE); + this.setPreferredSize(SIZE); + + JPanel mainPanel = new JPanel(new BorderLayout()); + + mainPanel.add(this.initCommandPanel(), BorderLayout.CENTER); + mainPanel.add(this.initRepoPanel(), BorderLayout.WEST); + + this.setContentPane(mainPanel); + + this.pack(); + this.initLoggingHandler(); + this.setVisible(true); + } + + /** + * @return A JPanel containing the command prompt field and output text pane. + */ + private JPanel initCommandPanel() { + JPanel commandPanel = new JPanel(new BorderLayout()); + // Output text pane. + this.outputTextPane = new OutputTextPane(); + JScrollPane scrollPane = new JScrollPane(this.outputTextPane); + scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + // Text enter field and label. + JPanel textEnterPanel = new JPanel(new BorderLayout()); + textEnterPanel.setBorder(BorderFactory.createLoweredBevelBorder()); + textEnterPanel.add(new JLabel("Command:"), BorderLayout.WEST); + JTextField commandField = new JTextField(); + commandField.addKeyListener(new CommandFieldKeyListener()); + textEnterPanel.add(commandField, BorderLayout.CENTER); + // Top Label + JLabel commandPanelLabel = new JLabel("Program output", SwingConstants.CENTER); + + commandPanel.add(scrollPane, BorderLayout.CENTER); + commandPanel.add(textEnterPanel, BorderLayout.SOUTH); + commandPanel.add(commandPanelLabel, BorderLayout.NORTH); + return commandPanel; + } + + /** + * @return A JPanel containing a list of repositories. + */ + private JPanel initRepoPanel() { + JPanel repoPanel = new JPanel(); + repoPanel.setLayout(new BoxLayout(repoPanel, BoxLayout.PAGE_AXIS)); + repoPanel.add(new JLabel("Repositories")); + repoPanel.add(new JList()); + return repoPanel; + } + +} diff --git a/src/main/java/nl/andrewlalis/ui/view/OutputTextPane.java b/src/main/java/nl/andrewlalis/ui/view/OutputTextPane.java new file mode 100644 index 0000000..64569cd --- /dev/null +++ b/src/main/java/nl/andrewlalis/ui/view/OutputTextPane.java @@ -0,0 +1,83 @@ +package nl.andrewlalis.ui.view; + +import javax.swing.*; +import javax.swing.text.BadLocationException; +import javax.swing.text.Style; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledDocument; +import java.awt.*; +import java.util.HashMap; +import java.util.Map; + +/** + * A custom JTextPane object which provides easy methods to print to the screen. + */ +public class OutputTextPane extends JTextPane { + + /** + * A list of named styles. + */ + private Map styles; + + /** + * A basic constructor to set default properties on this text pane. + */ + public OutputTextPane() { + this.initStyles(); + this.setEditable(false); + this.setAutoscrolls(true); + } + + private void initStyles() { + this.styles = new HashMap<>(); + Style defaultStyle = this.addStyle("default", null); + defaultStyle.addAttribute(StyleConstants.FontFamily, "Lucida Consonle"); + defaultStyle.addAttribute(StyleConstants.FontSize, 12); + this.styles.put("default", defaultStyle); + + Style grayItalics = this.addStyle("gray_italics", defaultStyle); + grayItalics.addAttribute(StyleConstants.Foreground, new Color(128, 128, 128)); + grayItalics.addAttribute(StyleConstants.Italic, true); + this.styles.put("gray_italics", grayItalics); + + Style bold = this.addStyle("bold", defaultStyle); + bold.addAttribute(StyleConstants.Bold, true); + this.styles.put("bold", bold); + + Style smaller = this.addStyle("smaller", defaultStyle); + smaller.addAttribute(StyleConstants.FontSize, 11); + this.styles.put("smaller", smaller); + } + + /** + * Prints some text styled with a style that is defined in initStyles. + * @param text The text to display. + * @param styleName The name of the style to use. + */ + public void printStyled(String text, String styleName) { + StyledDocument doc = this.getStyledDocument(); + Style style = this.styles.get(styleName); + if (style == null) { + style = this.styles.get("default"); + } + try { + doc.insertString(doc.getLength(), text, style); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + /** + * Prints a line of text, with a newline character appended at the bottom. + * @param text The text to append. + */ + public void printLine(String text) { + StyledDocument doc = this.getStyledDocument(); + try { + doc.insertString(doc.getLength(), (text + '\n'), null); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/nl/andrewlalis/util/FileUtils.java b/src/main/java/nl/andrewlalis/util/FileUtils.java index 809d2bd..f5cf3db 100644 --- a/src/main/java/nl/andrewlalis/util/FileUtils.java +++ b/src/main/java/nl/andrewlalis/util/FileUtils.java @@ -1,14 +1,26 @@ package nl.andrewlalis.util; +import nl.andrewlalis.model.StudentTeam; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.util.List; +import java.util.logging.Logger; /** * Contains some methods which come in handy in lots of other places. */ public class FileUtils { + /** + * The logger for outputting debug info. + */ + private static final Logger logger = Logger.getLogger(FileUtils.class.getName()); + static { + logger.setParent(Logger.getGlobal()); + } + /** * Reads the contents of the file specified by the filename into a String. * @param filename The filename to read the file of, either relative or absolute. @@ -28,4 +40,23 @@ public class FileUtils { } } + /** + * Reads a list of students from a CSV file and compiles a list of teams based on their preferred partners. + * @param filename The name of the CSV file. + * @param teamSize The intended size of teams. + * @return A list of student teams. + */ + public static List getStudentTeamsFromCSV(String filename, int teamSize) { + List studentTeams = null; + try { + studentTeams = TeamGenerator.generateFromCSV(filename, teamSize); + logger.fine("Teams created:\n" + studentTeams); + return studentTeams; + } catch (IOException | ArrayIndexOutOfBoundsException e) { + logger.severe("Unable to generate studentTeams from CSV file, exiting."); + System.exit(1); + return null; + } + } + } diff --git a/src/main/java/nl/andrewlalis/util/Logging.java b/src/main/java/nl/andrewlalis/util/Logging.java index e8e4124..b9b7113 100644 --- a/src/main/java/nl/andrewlalis/util/Logging.java +++ b/src/main/java/nl/andrewlalis/util/Logging.java @@ -20,10 +20,12 @@ public class Logging { outputFile.setFormatter(formatter); outputFile.setLevel(Level.FINEST); - Handler systemOut = new ConsoleHandler(); - systemOut.setLevel(Level.ALL); + if (verbose) { + Handler systemOut = new ConsoleHandler(); + systemOut.setLevel(Level.ALL); - //logger.addHandler(systemOut); + logger.addHandler(systemOut); + } logger.addHandler(outputFile); logger.setLevel(Level.ALL);