package net.cbaines.suca; import java.awt.Container; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.StringReader; import java.lang.reflect.InvocationTargetException; import javax.security.auth.login.LoginException; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.JApplet; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPasswordField; import javax.swing.JProgressBar; import javax.swing.JTabbedPane; import javax.swing.JTextField; import javax.swing.SwingUtilities; import net.fortuna.ical4j.data.CalendarBuilder; import net.fortuna.ical4j.data.ParserException; import net.fortuna.ical4j.model.Calendar; import org.apache.commons.io.IOUtils; @SuppressWarnings("serial") public class CalendarApplet extends JApplet { private CalendarApplet instance; // The panel holding the stages private Container stages; // Load University Calendar private JPanel calendarLoadingPanel; private JTextField usernameTextField; private JPasswordField passwordTextField; private JButton fetchCalendarButton; private JProgressBar fetchCalendarProgress; private JButton uploadCSVButton; // iCal Calendar Creation Options private JPanel calendarCreationOptions; private JCheckBox mergeDuplicateEventsWithSeperateLocations = new JCheckBox( "Merge Duplicate Events with Seperate Locations", true); private JCheckBox showTerms = new JCheckBox("Show Terms", true); private JCheckBox showSemesters = new JCheckBox("Show Semesters", true); private JCheckBox showSemesterWeeks = new JCheckBox("Show Semester Weeks", true); private JCheckBox mergeHeaders = new JCheckBox("Merge Headers", false); // Download Calendar private JPanel downloadCalendarPanel; private JButton donwloadCalendarButton; // Data private volatile String calendarCSVString = null; private volatile Calendar calendar = null; private final SotonCalendarParser calParser = new SotonCalendarParser(); public void init() { try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { try { stages = getContentPane(); stages.setLayout(new BoxLayout(stages, BoxLayout.PAGE_AXIS)); // Load University Calendar Stage calendarLoadingPanel = new JPanel(); calendarLoadingPanel.setBorder(BorderFactory.createTitledBorder("Load University Calendar")); JTabbedPane calendarLoadingChoiceTabbedPane = new JTabbedPane(); JPanel downloadPanel = new JPanel(); JPanel usernamePanel = new JPanel(); usernamePanel.add(new JLabel("Username")); usernameTextField = new JTextField(10); usernamePanel.add(usernameTextField); downloadPanel.add(usernamePanel); JPanel passwordPanel = new JPanel(); passwordPanel.add(new JLabel("Password")); passwordTextField = new JPasswordField(10); passwordPanel.add(passwordTextField); downloadPanel.add(passwordPanel); fetchCalendarButton = new JButton("Fetch Calendar"); fetchCalendarButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { fetchCalendarButton.setEnabled(false); fetchCalendarProgress.setIndeterminate(true); fetchCalendarProgress.setValue(0); new Thread(new DownloadCSV()).start(); } }); downloadPanel.add(fetchCalendarButton); calendarLoadingChoiceTabbedPane.addTab("Download Calendar", downloadPanel); JPanel uploadPanel = new JPanel(); uploadCSVButton = new JButton("Upload CSV"); uploadCSVButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { JFileChooser fc = new JFileChooser(); int returnVal = fc.showOpenDialog(instance); // this = Applet if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile(); try { new Thread(new UploadCSV(IOUtils.toString(new FileReader(file)))).start(); } catch (IOException e) { e.printStackTrace(); } } } }); uploadPanel.add(uploadCSVButton); calendarLoadingChoiceTabbedPane.addTab("Upload Calendar", uploadPanel); calendarLoadingPanel.add(calendarLoadingChoiceTabbedPane); fetchCalendarProgress = new JProgressBar(); fetchCalendarProgress.setIndeterminate(false); fetchCalendarProgress.setValue(0); calendarLoadingPanel.add(fetchCalendarProgress); stages.add(calendarLoadingPanel); // iCal Calendar Creation Options calendarCreationOptions = new JPanel(); calendarCreationOptions.setBorder(BorderFactory.createTitledBorder("Calendar Options")); calendarCreationOptions.add(mergeDuplicateEventsWithSeperateLocations); calendarCreationOptions.add(showTerms); calendarCreationOptions.add(showSemesters); calendarCreationOptions.add(showSemesterWeeks); calendarCreationOptions.add(mergeHeaders); setStageTwo(false); stages.add(calendarCreationOptions); // Calendar Download downloadCalendarPanel = new JPanel(); downloadCalendarPanel.setBorder(BorderFactory.createTitledBorder("Download Calendar (iCal)")); donwloadCalendarButton = new JButton("Download Calendar"); donwloadCalendarButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { Thread creationThread = new Thread(new CreateCalendar()); creationThread.start(); JFileChooser fc = new JFileChooser(); int returnVal = fc.showSaveDialog(instance); // this = Applet if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile(); try { creationThread.join(); } catch (InterruptedException e1) { e1.printStackTrace(); } try { BufferedWriter out = new BufferedWriter(new FileWriter(file)); out.write(calendar.toString()); out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } } } }); downloadCalendarPanel.add(donwloadCalendarButton); setStageThree(false); stages.add(downloadCalendarPanel); } catch (Exception e) { e.printStackTrace(); } } }); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } private void setStageTwo(boolean enable) { calendarCreationOptions.setEnabled(enable); mergeDuplicateEventsWithSeperateLocations.setEnabled(enable); showTerms.setEnabled(enable); showSemesters.setEnabled(enable); showSemesterWeeks.setEnabled(enable); mergeHeaders.setEnabled(enable); } private void setStageThree(boolean enable) { downloadCalendarPanel.setEnabled(enable); donwloadCalendarButton.setEnabled(enable); } private class UploadCSV implements Runnable { private String csvString; UploadCSV(String csvString) { this.csvString = csvString; } @Override public void run() { try { createCalendar(csvString); calendarCSVString = csvString; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { fetchCalendarButton.setEnabled(true); fetchCalendarProgress.setIndeterminate(false); fetchCalendarProgress.setValue(100); setStageTwo(true); setStageThree(true); } }); } catch (IOException e) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { fetchCalendarButton.setEnabled(true); fetchCalendarProgress.setIndeterminate(false); fetchCalendarProgress.setValue(0); JOptionPane.showMessageDialog(instance, "IOException: Error loading csv file", "Inane error", JOptionPane.ERROR_MESSAGE); } }); } catch (ParserException e) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { fetchCalendarButton.setEnabled(true); fetchCalendarProgress.setIndeterminate(false); fetchCalendarProgress.setValue(0); JOptionPane.showMessageDialog(instance, "ParserException: Error parsing csv", "Inane error", JOptionPane.ERROR_MESSAGE); } }); } } } private class DownloadCSV implements Runnable { @Override public void run() { try { // Fetch String csvString = new SotonCalendarFetcher(usernameTextField.getText(), passwordTextField.getPassword()).fetchAndParseTimetable(); if (csvString == null) { System.err.println("Got a null string back from SotonCalendarFetcher"); } try { createCalendar(csvString); calendarCSVString = csvString; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { fetchCalendarButton.setEnabled(true); fetchCalendarProgress.setIndeterminate(false); fetchCalendarProgress.setValue(100); setStageTwo(true); setStageThree(true); } }); } catch (ParserException e) { e.printStackTrace(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { fetchCalendarButton.setEnabled(true); fetchCalendarProgress.setIndeterminate(false); fetchCalendarProgress.setValue(0); JOptionPane.showMessageDialog(instance, "ParserException: Error parsing the csv file", "Inane error", JOptionPane.ERROR_MESSAGE); } }); } catch (IOException e) { e.printStackTrace(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { fetchCalendarButton.setEnabled(true); fetchCalendarProgress.setIndeterminate(false); fetchCalendarProgress.setValue(0); JOptionPane.showMessageDialog(instance, "IOException: IO Exception when reading the csv?", "Inane error", JOptionPane.ERROR_MESSAGE); } }); } } catch (LoginException e) { e.printStackTrace(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { fetchCalendarButton.setEnabled(true); fetchCalendarProgress.setIndeterminate(false); fetchCalendarProgress.setValue(0); JOptionPane .showMessageDialog( instance, "LoginException: Error logging in, try again, and perhaps also try logging in to SUSSED", "Inane error", JOptionPane.ERROR_MESSAGE); } }); } catch (IOException e) { e.printStackTrace(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { fetchCalendarButton.setEnabled(true); fetchCalendarProgress.setIndeterminate(false); fetchCalendarProgress.setValue(0); JOptionPane.showMessageDialog(instance, "IOException: Error logging in, try again, and perhaps also try logging in to SUSSED", "Inane error", JOptionPane.ERROR_MESSAGE); } }); } } } private class CreateCalendar implements Runnable { @Override public void run() { try { calendar = createCalendar(calendarCSVString); } catch (ParserException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } private Calendar createCalendar(String csvString) throws IOException, ParserException { calParser.setMergeDuplicateEventsWithSeperateLocations(mergeDuplicateEventsWithSeperateLocations.isSelected()); calParser.setMergeHeaders(mergeHeaders.isSelected()); calParser.setShowSemesters(showSemesters.isSelected()); calParser.setShowSemesterWeeks(showSemesterWeeks.isSelected()); calParser.setShowTerms(showTerms.isSelected()); CalendarBuilder builder = new CalendarBuilder(calParser); return builder.build(new StringReader(csvString)); } }