Enrol.java


// IM264 Coursework - Course Enrolment System
// Eamonn Martin - BSc (hons) Computing - ID: 96/D59682

// package im264;

import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.sql.*;


// -------------------------
//  General-Purpose Classes
// -------------------------

// Useful static methods
class Lib {

	// Return the frame containing this EnrolPanel (or null)
	public static Frame parentFrame(Component c) {
		while (c.getParent()!=null) c = c.getParent();
		return c instanceof Frame ? (Frame)c : null;
	}
}

// A labelled text-field component
class LabelledTextField extends Panel {
	private TextField label, text;

	// Constructors
	public LabelledTextField(String ltext, int width) { this(ltext, width, true); }
	public LabelledTextField(String ltext, int width, boolean isEditable) {
		setLayout(new BorderLayout());
		add(label = new TextField(ltext, width), "West");
		label.setEnabled(false);
		add(text = new TextField(), "Center");
		text.setEditable(isEditable);
		text.addFocusListener(new FocusListener() {	// Tidy-up Explorer applet!
			public void focusGained(FocusEvent e) {
				text.setCaretPosition(text.getText().length());
			}
			public void focusLost(FocusEvent e) {
				text.setCaretPosition(0);
			}
		});
	}

	// Query
	public String getLabel() { return label.getText(); }
	public String getText() { return text.getText(); }

	// Update
	public void setLabel(String label) { this.label.setText(label); }
	public void setText(String text) { this.text.setText(text); }
}

// A panel of labelled text-fields
class TextForm extends Panel {
	private LabelledTextField[] fields;

	// Constructors
	public TextForm(String[] labels, int width) {
		this(labels, width, new GridLayout(labels.length, 1));
	}
	public TextForm(String[] labels, int width, LayoutManager mngr) {
		setLayout(mngr);
		fields = new LabelledTextField[labels.length];
		for (int i=0; i < labels.length; ++i)
			add(fields[i] = new LabelledTextField(labels[i], width));
	}

	// Return the array of LabelledTextField components
	public LabelledTextField[] getFields() { return fields; }

	// Return the seperator-string to use between labels and text in getText()
	public String getSep() { return " "; }

	// Return the terminator-string to end a field in getText()
	public String getTerm() { return "\n"; }

	// Return all text from the LabelledTextField components on this panel
	public String getText() { return getText(null, null, true); }
	public String getText(String sep, String term, boolean labels) {
		LabelledTextField f;
		String s = "";
		if (term==null) term = getTerm();
		if (sep==null) sep = getSep();
		for (int i=0; i < fields.length; ++i) {
			f = fields[i];
			if (labels) s += f.getLabel() + sep;
			s += f.getText() + term;
		}
		return s;
	}
}

// A panel of check-boxes
class CheckboxPanel extends Panel {
	private CheckboxGroup group;

	// Constructors
	public CheckboxPanel() { this(new GridLayout()); }
	public CheckboxPanel(LayoutManager manager) {
		group = new CheckboxGroup();
		setLayout(manager);
	}

	// Add a checkbox with the specified label, state and event-handler
	public void addCheckbox(String label, ItemListener listener, boolean state) {
		Checkbox checkbox = new Checkbox(label, group, state);
		checkbox.addItemListener(listener);
		add(checkbox);
	}
}


// ------------------------------
//  Application-Specific Classes
// ------------------------------

// Manage interactions with the enrolment database
class EnrolDatabase {

	// Database access strings
	private static final String
		DRIVER			= "sun.jdbc.odbc.JdbcOdbcDriver",
		PROTOCOL		= "jdbc:odbc:",
		USERNAME		= null,
		PASSWORD		= null;

	// Table ID values
	static final int
		COURSE			= 0,
		STUDENT			= 1,
		CHEQUE			= 2,
		CREDITCARD		= 3,
		PURCHASEORDER		= 4;

	// Database definitions
	private static final String
		DATABASE		= "Enrol",

		TABLE_COURSE		= "Course",
		COLUMNS_COURSE		= "code, title, maxEnrol",

		TABLE_STUDENT		= "Student",
		STUDENT_COURSE		= "course",
		COLUMNS_STUDENT		= "id, "+STUDENT_COURSE+", name, tel, fax, email",
		STUDENT_PAID		= "paid",
		STUDENT_INFO		= "name, attended, " + STUDENT_PAID,

		TABLE_CHEQUE		= "Cheque",
		COLUMNS_CHEQUE		= "id, number",

		TABLE_CREDITCARD	= "CreditCard",
		COLUMNS_CREDITCARD	= "id, number, expiry, name",

		TABLE_PURCHASEORDER	= "PurchaseOrder",
		COLUMNS_PURCHASEORDER	= "id, number, company, name, tel";


	// Column indices for the Course table
	private static final int
		COL_CODE		= 1,
		COL_TITLE		= 2,
		COL_MAXENROL		= 3;

	// Column indices for the Student table
	private static final int
		COL_NAME		= 1,
		COL_ATTENDED		= 2,
		COL_PAID		= 3;


	// Attempt to open a connection to the database
	private static Connection getConnection() throws Exception {
		Class.forName(DRIVER);					// Load driver
		String url = PROTOCOL + DATABASE;			// Create URL
		return DriverManager.getConnection(url, USERNAME, PASSWORD);
	}

	// Query the database to determine the number of students enroled for a course
	private static int getNumEnroled(String code, Connection c) {
		try {
			Statement s = c.createStatement();
			String q = "SELECT COUNT(*) FROM " + TABLE_STUDENT +
				   " WHERE " + STUDENT_COURSE + "='" + code + "';";
			ResultSet r = s.executeQuery(q);
			int n = r.next() ? r.getInt(1) : -1;
			s.close();
			return n;
		} catch (SQLException e) {}
		return -1;
	}

	// Retrieve course information from the database (*IMPLEMENTS TEST-MODE*)
	static CourseData[] getCourses() {
	        try {
			Connection c = getConnection();			// Connect
			Statement s = c.createStatement();		// Create statement
			String q = "SELECT "+COLUMNS_COURSE+" FROM "+TABLE_COURSE+";";
			ResultSet r = s.executeQuery(q);		// Execute query

			CourseData data = new CourseData(), d = data;
			int num = 0;
			while (r.next()) {
				d = (d.next = new CourseData());
				d.code = r.getString(COL_CODE);		// Course code
				d.title = r.getString(COL_TITLE);	// Course title
				d.maxEnrol = r.getInt(COL_MAXENROL);	// Enrolment limit
				d.numEnrol = getNumEnroled(d.code, c);	// Enrolment count
				++num;
			}
			CourseData[] courses = new CourseData[num];
			for (int i=0; i < num; ++i) courses[i] = (data = data.next);
			return courses;
		} catch(Exception e) { System.out.println(e); }
		if (Enrol.READTEST) return getDummyCourses();		// Test-mode?
		return null;	// Failed
	}

	// Update a database table with a set of values (*IMPLEMENTS TEST-MODE*)
	static boolean update(int tableID, String values) {
		String name = null, cols = null;
		switch (tableID) {
		    case STUDENT:
			name = TABLE_STUDENT;
			cols = COLUMNS_STUDENT;
			break;
		    case CHEQUE:
			name = TABLE_CHEQUE;
			cols = COLUMNS_CHEQUE;
			break;
		    case CREDITCARD:
			name = TABLE_CREDITCARD;
			cols = COLUMNS_CREDITCARD;
			break;
		    case PURCHASEORDER:
			name = TABLE_PURCHASEORDER;
			cols = COLUMNS_PURCHASEORDER;
			break;
		    default:	return false;
		}
		String table = name + " (" + cols + ")";
		try {
			Connection c = getConnection();			// Connect
			Statement s = c.createStatement();		// Create statement
			String u = "INSERT INTO " + table + " VALUES (" + values + ");";
			s.executeUpdate(u);				// Execute update
			return true;					// Success
		} catch(Exception e) { System.out.println(e); }		// Error?
		if (Enrol.WRITETEST) return true;			// Test-mode?
		return false;
	}

	// Attempt to retrieve student information from the database
	private static StudentData[] getStudentInfo(String query) {
		try {
			Connection c = getConnection();			// Connect
			Statement s = c.createStatement();		// Create statement
			ResultSet r = s.executeQuery(query);		// Execute query

			StudentData data = new StudentData(), d = data;
			int num = 0;
			while (r.next()) {
				d = (d.next = new StudentData());
				d.name = r.getString(COL_NAME);		// Student name
				d.attended = r.getInt(COL_ATTENDED)!=0;	// Attendance
				d.paid = r.getInt(COL_PAID)!=0;		// Payment
				++num;
			}
			StudentData[] students = new StudentData[num];
			for (int i=0; i < num; ++i) students[i] = (data = data.next);
			return students;
		} catch(Exception e) { System.out.println(e); }
		return null;	// Failed
	}

	// Return students enroled on a specific course (*IMPLEMENTS TEST-MODE*)
	static StudentData[] getStudents(CourseData course) {
		String s = "SELECT " + STUDENT_INFO + " FROM " + TABLE_STUDENT +
			   " WHERE " + STUDENT_COURSE + "='" + course.code + "';";
		StudentData[] info = getStudentInfo(s);			// Execute query
		if (info!=null) return info;				// Query ok?
		return Enrol.READTEST ? getDummyStudents() : null;	// Test-mode?
	}

	// Return students with unpaid balances (*IMPLEMENTS TEST-MODE*)
	static StudentData[] getUnpaid() {
		String s = "SELECT " + STUDENT_INFO + " FROM " + TABLE_STUDENT +
			   " WHERE " + STUDENT_PAID + "=0;";
		StudentData[] info = getStudentInfo(s);			// Execute query
		if (info!=null) return info;				// Query ok?
		return Enrol.READTEST ? getDummyUnpaid() : null;	// Test-mode?
	}


	// The following methods are used to implement an offline test-mode

	// TEST-MODE - Return a dummy course-list
	private static CourseData[] getDummyCourses() {
		CourseData
			c1 = new CourseData("CODEG", "BSc Computer Science", 60, 40),
			c2 = new CourseData("CUDEG", "BSc Computing", 60, 35),
			courses[] = { c1, c2 };
		return courses;
	}

	// TEST-MODE - Return a dummy student-list
	private static StudentData[] getDummyStudents() {
		StudentData
			s1 = new StudentData("Brian Kernighan", true, true),
			s2 = new StudentData("Bill Gates", false, true),
			s3 = new StudentData("Steve Jobbs", true, false),
			s4 = new StudentData("Linus Torvalds", false, false),
			students[] = { s1, s2, s3, s4 };
		return students;
	}

	// TEST-MODE - Return a dummy unpaid-list
	private static StudentData[] getDummyUnpaid() {
		StudentData
			s1 = new StudentData("Steve Jobbs", true, false),
			s2 = new StudentData("Linus Torvalds", false, false),
			students[] = { s1, s2 };
		return students;
	}
}

// Class used to return course information from the database
class CourseData {
	String code, title;
	int maxEnrol, numEnrol;
	CourseData next;

	// Constructors
	CourseData() {}
	CourseData(String code, String title, int maxEnrol, int numEnrol) {
		this.code = code;
		this.title = title;
		this.maxEnrol = maxEnrol;
		this.numEnrol = numEnrol;
	}
}

// Class used to return student information from the database
class StudentData {
	String name;
	boolean attended, paid;
	StudentData next;

	// Constructors
	StudentData() {}
	StudentData(String name, boolean attended, boolean paid) {
		this.name = name;
		this.attended = attended;
		this.paid = paid;
	}
}


// ----------------------------------------------------------------------------------
//  The following component-classes are used to construct the DetailsPanel component
// ----------------------------------------------------------------------------------

// Course information component
class CourseInfo extends LabelledTextField {
	CourseInfo() { super("Course:", 14, false); }
	public String getText() { return getLabel() + " " + super.getText() + "\n"; }
}

// Student information component
class StudentInfo extends TextForm {
	private static final String[] labels = { "Name:", "Phone:", "Fax:", "E-mail:" };

	// Constructor
	StudentInfo() { super(labels, 14); }

	// Update the student table in the database
	boolean updateTable(CourseData course) {
		String v = getText(null, "', '", false);	// Get student input
		v = v.substring(0, v.length()-3);		// Remove last comma etc
		v = (course.numEnrol+1) + ", '" + course.code + "', '" + v;
		return EnrolDatabase.update(EnrolDatabase.STUDENT, v);
	}
}


// Payment Methods

// Interface implemented by payment-method classes
interface PaymentMethod {
	String getMethod();	// Return a string describing the payment-method
	String getText();	// Return the text of the input form (from TextForm)
}

// Generic super-class for payment-method TextForm components
class PaymentForm extends TextForm {
	private int table;

	// Constructor
	PaymentForm(int table, String[] labels, int width) {
		super(labels, width);
		this.table = table;
	}

	// Update the database with the text in this PaymentForm component
	boolean updateTable(CourseData course) {
		String v = getText(null, "', '", false);	// Format text values
		v = v.substring(0, v.length()-3);		// Remove last comma etc
		v = (course.numEnrol+1) + ", '" + v;		// Add new student ID
		return EnrolDatabase.update(table, v);		// Update database
	}
}

// Cheque information
class ChequeInfo extends PaymentForm implements PaymentMethod {
	private static final String[] labels = { "Number:" };
	ChequeInfo() { super(EnrolDatabase.CHEQUE, labels, 14); }
	public String getMethod() { return "Cheque"; }
}

// Credit card information
class CreditCardInfo extends PaymentForm implements PaymentMethod {
	private static final String[] labels = { "Number:", "Expiry:", "Name:" };
	CreditCardInfo() { super(EnrolDatabase.CREDITCARD, labels, 14); }
	public String getMethod() { return "Credit Card"; }
}

// Purchase Order information
class PurchaseOrderInfo extends PaymentForm implements PaymentMethod {
	private static final String[] labels =
		{ "Company:", "Order No:", "Contact Name:", "Contact Tel:" };
	PurchaseOrderInfo() { super(EnrolDatabase.PURCHASEORDER, labels, 14); }
	public String getMethod() { return "Purchase Order"; }
}

// Payment information component
class PaymentInfo extends Panel implements ItemListener {
	private static Class[] methodTypes = {
		ChequeInfo.class, CreditCardInfo.class, PurchaseOrderInfo.class
	};
	private PaymentMethod methods[], method;
	private CheckboxPanel selector;

	// Constructors
	PaymentInfo() { this(methodTypes); }
	PaymentInfo(Class[] methodTypes) {
		methods = new PaymentMethod[methodTypes.length];
		selector = new CheckboxPanel();
		boolean state = true;
		for (int i=0; i < methods.length; ++i) try {
			methods[i] = (PaymentMethod)methodTypes[i].newInstance();
			selector.addCheckbox(methods[i].getMethod(), this, state);
			state = false;
		} catch (Exception e) {}
		setLayout(new BorderLayout());
		add(selector, "North");
		add((Component)(method = methods[0]), "Center");
	}

	// Change payment method
	public void itemStateChanged(ItemEvent e) {
		String label = (String)e.getItem();
		remove((Component)method);
		for (int i=0; i < methods.length; ++i)
			if (label.equals(methods[i].getMethod()))
				add((Component)(method = methods[i]), "Center");
	}

	// Return payment details
	public String getText() {
		return "Method: " + method.getMethod() + "\n" + method.getText();
	}

	// Update the database table for the current payment method
	boolean updateTable(CourseData course) {
		return ((PaymentForm)method).updateTable(course);
	}
}


// ------------------------------------------------------------------------------------
//  The following three components are the display-panels for the EnrolPanel component
// ------------------------------------------------------------------------------------

// Course-list panel
class CoursePanel extends Panel {
	CourseData[] courses = null;
	private List course;

	// Constructors
	CoursePanel(ActionListener listener, String enrol) { this(listener, enrol, null); }
	CoursePanel(ActionListener listener, String cmd1, String cmd2) {
		setLayout(new BorderLayout());
		add(course = new List(10), "Center");
		String[] courses = getCourseList();
		if (courses!=null)
			for (int i=0; i < courses.length; ++i) course.add(courses[i]);
		Panel p = new Panel(new GridLayout());
		Button b = new Button(cmd1);			// Primary button
		b.setActionCommand(cmd1);
		b.addActionListener(listener);
		p.add(b);
		if (cmd2!=null) {				// Secondary button?
			b = new Button(cmd2);
			b.setActionCommand(cmd2);
			b.addActionListener(listener);
			p.add(b);
		}
		add(p, "South");				// Add button-panel
	}

	// Return an array of strings representing a list of courses
	private String[] getCourseList() {
		courses = EnrolDatabase.getCourses();		// Access database
		if (courses==null) return null;			// Access failed?
		String[] s = new String[courses.length];
		CourseData c;
		for (int i=0; i < courses.length; ++i) {
			c = courses[i];
			s[i] = c.code + " " + c.title;
			if (c.numEnrol>=c.maxEnrol) s[i] += " (SOLD OUT)";
		}
		return s;
	}

	// Return the currently selected text (ie. course)
	public String getText() { return course.getSelectedItem(); }

	// Return the CourseData for the currently selected course
	CourseData getCourse() {
		int i = course.getSelectedIndex();
		return (i < 0) ? null : courses[i];
	}
}

// Enrolment details panel
class DetailsPanel extends Panel {
	private CourseInfo course;
	private StudentInfo student;
	private PaymentInfo payment;

	DetailsPanel(ActionListener listener, String submit, String cancel) {
		setLayout(new BorderLayout());
		Panel form = new Panel(new BorderLayout());

		Panel p = new Panel(new BorderLayout());
		p.add(course = new CourseInfo(), "North");
		p.add(student = new StudentInfo(), "Center");
		form.add(p, "North");
		form.add(payment = new PaymentInfo() {
			public void itemStateChanged(ItemEvent e) {
				super.itemStateChanged(e);
				Lib.parentFrame(this).validate();
			}
		}, "South");
		add(form, "North");

		p = new Panel(new GridLayout());
		Button b = new Button(submit);
		b.setActionCommand(submit);
		b.addActionListener(listener);
		p.add(b);
		b = new Button(cancel);
		b.setActionCommand(cancel);
		b.addActionListener(listener);
		p.add(b);
		add(p, "South");
	}

	// Set the course description for this enrolment panel
	void setCourse(String course) { this.course.setText(course); }

	// Update the database
	boolean submit(CourseData data) {
		if (student.updateTable(data))			// Update student table
		 if (payment.updateTable(data))			// Update payment table
		  return true;
		return false;
	}

	// Return a summary of the text on this enrolment panel
	String getText() {
		return	"\n" + course.getText() +
			"\nSTUDENT DETAILS\n" + student.getText() +
			"\nPAYMENT DETAILS\n" + payment.getText();
	}
}

// Application summary panel
class SummaryPanel extends Panel {
	private static final String
		msgOk = "\n Your application has been registered.  Thank you.\n\n" +
			" This is your completed course application form.\n\n" +
			" To complete your application, print this page, sign\n" +
			" the printed copy and fax it to the enrolment centre.",
		msgErr=	"\n A SYSTEM ERROR HAS OCCURRED!\n\n" +
			" Please re-submit your application.",
		msgSig=	"\nSIGNED:";
	private TextArea msg, info;

	// Constructor
	SummaryPanel(ActionListener listener, String finish) {
		setLayout(new BorderLayout());
		add(msg = new TextArea("", 7, 40, TextArea.SCROLLBARS_NONE), "North");
		msg.setEditable(false);
		add(info = new TextArea("", 17, 40, TextArea.SCROLLBARS_NONE), "Center");
		info.setEditable(false);
		Button b = new Button(finish);
		b.setActionCommand(finish);
		b.addActionListener(listener);
		add(b, "South");
	}

	// Set the text for this SummaryPanel
	void setText(String text) {
		if (text!=null) {				// All okay?
			msg.setForeground(Color.blue);
			msg.setText(msgOk);
			info.setText(text + msgSig);
		} else {					// Error
			msg.setForeground(Color.red);
			msg.setText(msgErr);
			info.setText("");
		}
	}
}


// --------------------------------------------------------------------------------
//  The following components are extra display-panels for the ClerkPanel component
// --------------------------------------------------------------------------------

// Generic super-class for text-output panels
class TextPanel extends Panel {
	TextArea text;

	// Constructor
	TextPanel(ActionListener listener, String cancel) {
		super(new BorderLayout());
		add(text = new TextArea(), "Center");
		text.setEditable(false);
		Button b = new Button(cancel);
		b.setActionCommand(cancel);
		b.addActionListener(listener);
		add(b, "South");
	}

	// Return a list of student-information as a text string
	String getStudentList(StudentData[] students) {
		String text = "";
		if (students!=null) for (int i=0; i < students.length; ++i) {
			StudentData s = students[i];
			text += s.name;
			if (s.attended||s.paid) {
				text += " (";
				if (s.attended) text += "attended";
				if (s.attended&&s.paid) text += ", ";
				if (s.paid) text += "paid";
				text += ")";
			}
			text += "\n";
		}
		return text;
	}
}

// Student status information
class StatusPanel extends TextPanel {

	// Constructor
	StatusPanel(ActionListener listener, String cancel) { super(listener, cancel); }

	// Create a list of the students on a given course
	void setCourse(CourseData data) {
		String s = data.code + " " + data.title + "\n\n";
		s += getStudentList(EnrolDatabase.getStudents(data));
		text.setText(s);
	}
}

// Outstanding balance information
class UnpaidPanel extends TextPanel {

	// Constructor
	UnpaidPanel(ActionListener listener, String cancel) {
		super(listener, cancel);
		String s = getStudentList(EnrolDatabase.getUnpaid());
		text.setText("Unpaid Balances\n\n" + s);
	}
}


// ---------------------
//  Main display panels
// ---------------------

// Generic super-class for top-level display panels
class MainPanel extends Panel {
	Panel oldPanel = null;

	// Constructor
	MainPanel() { setLayout(new BorderLayout()); }

	// Replace oldPanel with newPanel
	void setPanel(Panel newPanel) {
		remove(oldPanel);
		add(newPanel, "Center");
		Lib.parentFrame(this).validate();
		oldPanel = newPanel;
	}
}

// Enrolment display panel
class EnrolPanel extends MainPanel implements ActionListener {
	private CoursePanel course;
	private DetailsPanel details;
	private SummaryPanel summary;
	private CourseData data;

	// Constructor
	EnrolPanel() {
		course = new CoursePanel(this, "Enrol");
		details = new DetailsPanel(this, "Submit", "Cancel");
		summary = new SummaryPanel(this, "Finish");
		add(oldPanel = course, "Center");
	}

	// Process button-presses from the sub-panels
	public void actionPerformed(ActionEvent e) {
		String cmd = e.getActionCommand();
		if (cmd.equals("Enrol")) {			// Course -> Details
			data = course.getCourse();		// Get course data
			if (data==null) return;			// No course selected?
			details.setCourse(course.getText());	// Set course name
			setPanel(details);			// Swap panels
		} else if (cmd.equals("Cancel")) {		// Details -> Course
			setPanel(course);			// Swap panels
		} else if (cmd.equals("Submit")) {		// Details -> Summary
			String s = details.submit(data) ? details.getText() : null;
			summary.setText(s);			// Write summary
			setPanel(summary);			// Swap panels
		} else if (cmd.equals("Finish")) {		// Summary -> Course
			setPanel(course);			// Swap panels
		}
	}
}

// Clerk display panel
class ClerkPanel extends MainPanel implements ActionListener {
	private CoursePanel course;
	private StatusPanel status;
	private UnpaidPanel unpaid;
	private CourseData data;

	ClerkPanel() {
		course = new CoursePanel(this, "Students", "Unpaid");
		status = new StatusPanel(this, "Cancel");
		unpaid = new UnpaidPanel(this, "Cancel");
		add(oldPanel = course, "Center");
	}

	// Process button-presses from the sub-panels
	public void actionPerformed(ActionEvent e) {
		String cmd = e.getActionCommand();
		if (cmd.equals("Students")) {			// Course -> Status
			data = course.getCourse();		// Get course data
			if (data==null) return;			// No course selected?
			status.setCourse(data);			// Create status list
			setPanel(status);			// Swap panels
		} else if (cmd.equals("Unpaid")) {		// Course -> Unpaid
			setPanel(unpaid);			// Swap panels
		} else if (cmd.equals("Cancel")) {		// Status/Unpaid -> Course
			setPanel(course);			// Swap panels
		}
	}
}

// Main program class
public class Enrol extends java.applet.Applet {

	// Debug-mode flags
	static final boolean
		READTEST = true,				// Ignore read-errors
		WRITETEST = true;				// Ignore write-errors

	// Start the applet
	public void init() {
		setLayout(new BorderLayout());
		String s = getParameter("mode");		// Get mode from HTML
		Component c;
		if (s!=null) if (!s.equals("clerk")) s = null;	// Clerk-mode parameter?
		if (s!=null) c = new ClerkPanel();		// Clerk mode
		else c = new EnrolPanel();			// Enrolment mode
		add(c, "Center");				// Add chosen panel
	}

	// Start the application
	public static void main(String[] args) {
		Frame win = new Frame("Course Enrolment System");
		win.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e){ e.getWindow().dispose();}
			public void windowClosed(WindowEvent e) { System.exit(0); }
		});
		win.add(new ClerkPanel(), "Center");		// Clerk panel
		win.pack();
		win.show();
	}
}

Go To: IM264: Object-Oriented Concepts