diff --git a/year4/semester2/CT414/assignments/assignment1/code/.gitignore b/year4/semester2/CT414/assignments/assignment1/code/.gitignore new file mode 100644 index 00000000..23e58aca --- /dev/null +++ b/year4/semester2/CT414/assignments/assignment1/code/.gitignore @@ -0,0 +1,32 @@ +### IntelliJ IDEA ### +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ +.idea/ + +### Mac OS ### +.DS_Store + +code.iml diff --git a/year4/semester2/CT414/assignments/assignment1/code/src/exceptions/InvalidCredentialsException.java b/year4/semester2/CT414/assignments/assignment1/code/src/exceptions/InvalidCredentialsException.java new file mode 100644 index 00000000..bec1d03d --- /dev/null +++ b/year4/semester2/CT414/assignments/assignment1/code/src/exceptions/InvalidCredentialsException.java @@ -0,0 +1,13 @@ +package exceptions; + +import java.rmi.RemoteException; + +public class InvalidCredentialsException extends RemoteException { + public InvalidCredentialsException() { + super("Invalid username or password."); + } + + public InvalidCredentialsException(String message) { + super(message); + } +} diff --git a/year4/semester2/CT414/assignments/assignment1/code/src/exceptions/InvalidSessionIDException.java b/year4/semester2/CT414/assignments/assignment1/code/src/exceptions/InvalidSessionIDException.java new file mode 100644 index 00000000..2d60f8f9 --- /dev/null +++ b/year4/semester2/CT414/assignments/assignment1/code/src/exceptions/InvalidSessionIDException.java @@ -0,0 +1,13 @@ +package exceptions; + +import java.rmi.RemoteException; + +public class InvalidSessionIDException extends RemoteException { + public InvalidSessionIDException() { + super("Invalid or expired session ID."); + } + + public InvalidSessionIDException(String message) { + super(message); + } +} diff --git a/year4/semester2/CT414/assignments/assignment1/code/src/implementations/ApplicationFormV1.java b/year4/semester2/CT414/assignments/assignment1/code/src/implementations/ApplicationFormV1.java new file mode 100644 index 00000000..c1ce4da6 --- /dev/null +++ b/year4/semester2/CT414/assignments/assignment1/code/src/implementations/ApplicationFormV1.java @@ -0,0 +1,57 @@ +package implementations; + +import interfaces.*; +import java.util.*; +import java.rmi.*; + +public class ApplicationFormV1 implements ApplicationForm { + private String formInfo = "University of Galway Application Form - Version 1"; + private String[] questions = new String[5]; + private String[] answers = new String[5]; + + public ApplicationFormV1() { + questions[0] = "What is your full name?"; + questions[1] = "What is your address?"; + questions[2] = "What is your e-mail address?"; + questions[3] = "What is your contact number?"; + questions[4] = "Provide a personal statement (e.g., additional details about yourself, a summary of your existing qualifications or results)."; + } + + @Override + public String getFormInfo() throws RemoteException { + return formInfo; + } + + @Override + public int getTotalQuestions() throws RemoteException { + return questions.length; + } + + @Override + public String getQuestion(int questionNumber) throws RemoteException, IllegalArgumentException { + if (questionNumber < 0 || questionNumber > questions.length) { + throw new IllegalArgumentException("Invalid question number: " + questionNumber); + } + return questions[questionNumber]; + } + + @Override + public void answerQuestion(int questionNumber, String answer) throws RemoteException, IllegalArgumentException { + if (questionNumber < 0 || questionNumber > questions.length) { + throw new IllegalArgumentException("Invalid question number: " + questionNumber); + } + answers[questionNumber] = answer; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < questions.length; i++) { + sb.append("Q").append(i).append(": ").append(questions[i]).append("\n"); + sb.append("A").append(i).append(": ").append(answers[i]).append("\n\n"); + } + + return sb.toString(); + } +} diff --git a/year4/semester2/CT414/assignments/assignment1/code/src/interfaces/ApplicationForm.java b/year4/semester2/CT414/assignments/assignment1/code/src/interfaces/ApplicationForm.java new file mode 100644 index 00000000..22db0ee0 --- /dev/null +++ b/year4/semester2/CT414/assignments/assignment1/code/src/interfaces/ApplicationForm.java @@ -0,0 +1,18 @@ +package interfaces; + +import java.rmi.*; + +public interface ApplicationForm extends Remote { + + // method to retrieve general information about the form + String getFormInfo() throws RemoteException; + + // method to retrieve the total number of questions in the application form + int getTotalQuestions() throws RemoteException; + + // method to retrieve a specific question based on its number + String getQuestion(int questionNumber) throws RemoteException, IllegalArgumentException; + + // method to provide a String answer to a question based off its questionNumber + void answerQuestion(int questionNumber, String answer) throws RemoteException, IllegalArgumentException; +} diff --git a/year4/semester2/CT414/assignments/assignment1/code/src/interfaces/ApplicationHandler.java b/year4/semester2/CT414/assignments/assignment1/code/src/interfaces/ApplicationHandler.java new file mode 100644 index 00000000..7cd5551c --- /dev/null +++ b/year4/semester2/CT414/assignments/assignment1/code/src/interfaces/ApplicationHandler.java @@ -0,0 +1,14 @@ +package interfaces; + +import exceptions.InvalidCredentialsException; +import exceptions.InvalidSessionIDException; + +import java.rmi.*; + +public interface ApplicationHandler extends Remote { + long login(String username, String password) throws RemoteException, InvalidCredentialsException; + + ApplicationForm downloadApplicationForm(long sessionID) throws RemoteException, InvalidSessionIDException; + + void submitApplicationForm(long sessionID, ApplicationForm applicationForm) throws RemoteException, InvalidSessionIDException; +} diff --git a/year4/semester2/CT414/assignments/assignment1/latex/CT414-Assignment-01.pdf b/year4/semester2/CT414/assignments/assignment1/latex/CT414-Assignment-01.pdf new file mode 100644 index 00000000..398042b0 Binary files /dev/null and b/year4/semester2/CT414/assignments/assignment1/latex/CT414-Assignment-01.pdf differ diff --git a/year4/semester2/CT414/assignments/assignment1/latex/CT414-Assignment-01.tex b/year4/semester2/CT414/assignments/assignment1/latex/CT414-Assignment-01.tex new file mode 100644 index 00000000..3fa9c3d3 --- /dev/null +++ b/year4/semester2/CT414/assignments/assignment1/latex/CT414-Assignment-01.tex @@ -0,0 +1,76 @@ +%! TeX program = lualatex +\documentclass[a4paper]{article} + +% packages +\usepackage{microtype} % Slightly tweak font spacing for aesthetics +\usepackage[english]{babel} % Language hyphenation and typographical rules +\usepackage[final, colorlinks = true, urlcolor = black, linkcolor = black]{hyperref} +\usepackage{changepage} % adjust margins on the fly + +\usepackage{fontspec} +\setmainfont{EB Garamond} +\setmonofont[Scale=MatchLowercase]{Deja Vu Sans Mono} + +\usepackage{minted} +\usemintedstyle{algol_nu} +\usepackage{xcolor} + +\usepackage{pgfplots} +\pgfplotsset{width=\textwidth,compat=1.9} + +\usepackage{caption} +\newenvironment{code}{\captionsetup{type=listing}}{} +\captionsetup[listing]{skip=0pt} +\setlength{\abovecaptionskip}{5pt} +\setlength{\belowcaptionskip}{5pt} + +\usepackage[yyyymmdd]{datetime} +\renewcommand{\dateseparator}{--} + +\usepackage{titlesec} +% \titleformat{\section}{\LARGE\bfseries}{}{}{}[\titlerule] +% \titleformat{\subsection}{\Large\bfseries}{}{0em}{} +% \titlespacing{\subsection}{0em}{-0.7em}{0em} +% +% \titleformat{\subsubsection}{\large\bfseries}{}{0em}{$\bullet$ } +% \titlespacing{\subsubsection}{1em}{-0.7em}{0em} + +% margins +\addtolength{\hoffset}{-2.25cm} +\addtolength{\textwidth}{4.5cm} +\addtolength{\voffset}{-3.25cm} +\addtolength{\textheight}{5cm} +\setlength{\parskip}{0pt} +\setlength{\parindent}{0in} +% \setcounter{secnumdepth}{0} + +\begin{document} +\hrule \medskip +\begin{minipage}{0.295\textwidth} + \raggedright + \footnotesize + \begin{tabular}{@{}l l} + Name: & Andrew Hayes \\ + Student ID: & 21321503 \\ + E-mail: & \href{mailto://a.hayes18@universityofgalway.ie}{\texttt{a.hayes18@universityofgalway.ie}} \\ + \end{tabular} +\end{minipage} +\begin{minipage}{0.4\textwidth} + \centering + \vspace{0.4em} + \LARGE + \textsc{ct414} \\ +\end{minipage} +\begin{minipage}{0.295\textwidth} + \raggedleft + \today +\end{minipage} +\medskip\hrule +\begin{center} + \normalsize + Assignment 1: Java RMI +\end{center} +\hrule + + +\end{document} diff --git a/year4/semester2/CT414/assignments/assignment1/specification.md b/year4/semester2/CT414/assignments/assignment1/specification.md new file mode 100644 index 00000000..8cbe30ff --- /dev/null +++ b/year4/semester2/CT414/assignments/assignment1/specification.md @@ -0,0 +1,19 @@ +# Problem Description +You are required to implement an Internet based College Course application system for the University using Java RMI. The server allows a client to login and retrieve an ApplicationForm object that will then be completed on the client side. The client can then submit the completed ApplicationForm object back to the server for validation and processing. The design of the system makes it possible for new ApplicationForm implementation classes to be easily added to the server in the future, making the system very flexible. + +# Implementation Details +The answer should include full source code for the following Java interfaces and classes: +- ApplicationHandler.java - this Java interface provides remote methods for user login, based on a username and password, downloading an Application Form and submitting a completed Application Form. If sucessful, the login method returns a long integer value that must be passed to the other two server methods as a session identifier. The methods to download and upload an Application Form object should use the interface type ApplicationForm as described next. Provide suitable exception handling for the remote methods to catch possible issues with parameters or method invocation e.g. InvalidCredentials, InvalidSessionID etc. +- ApplicationForm.java - this Java interface provides methods for retrieving and answering questions. The interface should have a method to retrieve general information about the application form and a method to return the total number of questions to be answered. It should also have methods to retrieve and answer questions, based on the question number, it only needs to support text type questions and answers. +- ApplicationFormV1.java - this Java class should provide an implementation of the ApplicationForm interface. It should include questions that allow the following information about the applicant to be included in a completed application form: name, address, email and contact number of the applicant. It should also have a question that allows an applicant to provide a personal statement e.g. this could be used to include additional details about the applicant and a summary of their existing qualifications or results. +- ApplicationHandlerImpl.java - this Java class should provide the implementation of the ApplicationHandler interface, an instance of this class will be created by the mainline server code. A single valid username and password can be hardcoded into the server for the purposes of implementing the login method. The implementation method to download an ApplicationForm therefore just needs to return an instance of the ApplicationFormV1 class. The CourseServer implementation method to upload a completed ApplicationForm should just save the completed form, in a suitable text format, to a file. For this purpose, the implementation class can include an appropriate toString() method. The filename used should be based on the first name and second name provided in the ApplicationForm. +- ApplicationServer.java - this Java class should provide the mainline server code. This should create an instance of the ApplicationHandlerImpl class and then register this with the RMIRegistry so that it can be located and used by the client code. +- ApplicationClient.java - this Java class should provide the client code. This can done as a simple command line client program that will interact with the server as follows: (i) Login to the server. (ii) Download an ApplicationForm object. (iii) Call methods on the ApplicationForm, as required to complete the form. (iv) Submit the completed Application Form back to the sever. +Completing the Assignment + +There are two main programming tasks. The first is to complete the implementation of the remote methods in the ApplicationHandlerImpl class, the second is to write the client program that can use and interact with the server i.e. it logs into the server to get an access token, it then downloads an ApplicationForm object, completes the form and then finally submits the ApplicationForm object back to the server. For the purposes of completing this assignment you can create just one ApplicationFormV1 object for testing purposes. Also, the server only needs to implement the remote interfaces provided i.e. there is no need to do any further processing on a completed ApplicationForm after it has been uploaded to the server other than to save a copy of the submission as a text file on the server. You do not need to implement a GUI or any interactive features for the client program, it can be done as a simple command line program that calls methods on the server and on an ApplicationForm object after it has been downloaded to the client. You should include some debug related print commands in both the client and server programs for testing and verification purposes. + +# Submission Details + +When completed you should submit copies of the source code you have written for the assignment as well as a document describing how you tested the application, the document should include screen shots showing evidence of the application running and the testing that was carried out. Please combine all the source code files and the related document (PDF or MS Word format only) into a single ZIP file for submission. All submissions should be done via Canvas and if you submit more than one attempt then only the final attempt will be marked. You can work on this assignment individually or in groups of no more than two students. In the case of a group submission only one member of the group needs to submit the assignment on Canvas, but please ensure that the ID number for both students is clearly indicated in the submission. +