diff --git a/src/data/FileDataModel.java b/src/data/FileDataModel.java index 326f288..70cf146 100644 --- a/src/data/FileDataModel.java +++ b/src/data/FileDataModel.java @@ -1,46 +1,98 @@ package data; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; import java.util.List; + import model.*; +import jsonlib.types.JSONObject; +import jsonlib.types.JSONList; +import jsonlib.types.JSONDict; +import jsonlib.JSONSerializableFactory; +import jsonlib.JSONParser; +import jsonlib.JSONExpectFailedException; public class FileDataModel { - public void loadBooks(String filePath) { - // TODO: Implement method 'filePath'. - throw new UnsupportedOperationException("Unimplemented method 'filePath'"); + private static final String BOOKS_FILEPATH = "books.json"; + private static final String STUDENTS_FILEPATH = "students.json"; + private static final String CATEGORIES_FILEPATH = "categories.json"; + private static final String LOANS_FILEPATH = "loans.json"; + + public List loadBooks() { + return loadFromFile(BOOKS_FILEPATH); + } + + public List loadStudents() { + return loadFromFile(STUDENTS_FILEPATH); } - public void saveBooks(List books, String filePath) { - // TODO: Implement method 'saveBooks'. - throw new UnsupportedOperationException("Unimplemented method 'saveBooks'"); + public List loadCategories() { + return loadFromFile(CATEGORIES_FILEPATH); } - public void loadStudents(String filePath) { - // TODO: Implement method 'loadStudents'. - throw new UnsupportedOperationException("Unimplemented method 'loadStudents'"); + public List loadLoans() { + return loadFromFile(LOANS_FILEPATH); } - public void saveStudents(List students, String filePath) { - // TODO: Implement method 'saveStudents'. - throw new UnsupportedOperationException("Unimplemented method 'saveStudents'"); + public void saveBooks(List books) { + writeToFile(BOOKS_FILEPATH, JSONObject.fromList(books).toString()); } - public void loadCategories(String filePath) { - // TODO: Implement method 'loadCategories'. - throw new UnsupportedOperationException("Unimplemented method 'loadCategories'"); + public void saveStudents(List students) { + writeToFile(STUDENTS_FILEPATH, JSONObject.fromList(students).toString()); } - public void saveCategories(List categories, String filePath) { - // TODO: Implement method 'saveCategories'. - throw new UnsupportedOperationException("Unimplemented method 'saveCategories'"); + public void saveCategories(List categories) { + writeToFile(CATEGORIES_FILEPATH, JSONObject.fromList(categories).toString()); } - public void loadLoans(String filePath) { - // TODO: Implement method 'loadLoans'. - throw new UnsupportedOperationException("Unimplemented method 'loadLoans'"); + public void saveLoans(List loans) { + writeToFile(LOANS_FILEPATH, JSONObject.fromList(loans).toString()); } - public void saveLoans(List loans, String filePath) { - // TODO: Implement method 'saveLoans'. - throw new UnsupportedOperationException("Unimplemented method 'saveLoans'"); + public void writeToFile(String filePath, String data) { + try (FileWriter writer = new FileWriter(filePath)) { + writer.write(data); + } catch (IOException e) { + e.printStackTrace(); + } } + + public String readFromFile(String filePath) { + String content = new String(); + try { + content = String.join("\n", Files.readAllLines(Paths.get(filePath))); + } catch (IOException e) { + e.printStackTrace(); + } + + return content; + } + + public List loadFromFile(String filePath) { + String content = readFromFile(filePath); + JSONParser parser = new JSONParser(content); + + JSONObject jsonObj = null; + + try { + jsonObj = parser.parse(); + } catch (JSONExpectFailedException e) { + e.printStackTrace(); + } + + List result = new ArrayList<>(); + JSONList listJSON = (JSONList) jsonObj; + + for (JSONObject itemJSON : listJSON) { + T item = (T) JSONSerializableFactory.deserialize((JSONDict) itemJSON); + result.add(item); + } + + return result; + } + } diff --git a/src/jsonlib/JSONExpectFailedException.java b/src/jsonlib/JSONExpectFailedException.java new file mode 100644 index 0000000..aad1e45 --- /dev/null +++ b/src/jsonlib/JSONExpectFailedException.java @@ -0,0 +1,8 @@ +package jsonlib; + +public class JSONExpectFailedException extends Exception { + + public JSONExpectFailedException(String msg) { + super(msg); + } +} diff --git a/src/jsonlib/JSONParser.java b/src/jsonlib/JSONParser.java index 565d8b3..7f255a2 100644 --- a/src/jsonlib/JSONParser.java +++ b/src/jsonlib/JSONParser.java @@ -1,5 +1,6 @@ package jsonlib; +import jsonlib.types.JSONBoolean; import jsonlib.types.JSONDict; import jsonlib.types.JSONList; import jsonlib.types.JSONNumber; @@ -80,7 +81,7 @@ private JSONNumber parseNumber() throws JSONExpectFailedException { StringBuilder integerPartStr = new StringBuilder(); StringBuilder floatingPartStr = new StringBuilder(); boolean isFloat = false; - + while (peek() != '\0' && Character.isDigit(peek())) integerPartStr.append(consume()); @@ -101,8 +102,13 @@ private JSONNumber parseNumber() throws JSONExpectFailedException { double number = Double.valueOf(integerPartStr + "." + floatingPartStr); return new JSONNumber(sign * number); } else { - int number = Integer.valueOf(integerPartStr.toString()); - return new JSONNumber(sign * number); + try { + int number = Integer.valueOf(integerPartStr.toString()); + return new JSONNumber(sign * number); + } catch (NumberFormatException e) { + long number = Long.valueOf(integerPartStr.toString()); + return new JSONNumber(sign * number); + } } } @@ -146,6 +152,16 @@ private JSONDict parseDict() throws JSONExpectFailedException { return dict; } + private JSONBoolean parseBoolean() throws JSONExpectFailedException { + if (peek() == 't') { + expect("true"); + return new JSONBoolean(true); + } else { + expect("false"); + return new JSONBoolean(false); + } + } + public JSONObject parse() throws JSONExpectFailedException { while (peek() != '\0') { switch (peek()) { @@ -160,11 +176,11 @@ public JSONObject parse() throws JSONExpectFailedException { return parseNumber(); else if (Character.isWhitespace(peek())) consume(); + else if (peek() == 't' || peek() == 'f') + return parseBoolean(); else // TODO: handle invalid characters properly. throw new UnsupportedOperationException("not implemented yet"); - - // TODO: handle json boolean and null break; } } @@ -172,10 +188,3 @@ else if (Character.isWhitespace(peek())) } } - -class JSONExpectFailedException extends Exception { - - public JSONExpectFailedException(String msg) { - super(msg); - } -} diff --git a/src/jsonlib/types/JSONBoolean.java b/src/jsonlib/types/JSONBoolean.java new file mode 100644 index 0000000..88cdca0 --- /dev/null +++ b/src/jsonlib/types/JSONBoolean.java @@ -0,0 +1,36 @@ +package jsonlib.types; + +public class JSONBoolean extends JSONObject { + private boolean value; + + public JSONBoolean(boolean value) { + this.value = value; + } + + public boolean getValue() { + return this.value; + } + + @Override + public String toString() { + return value ? "true" : "false"; + } + + @Override + public int hashCode() { + return this.value ? 1 : 0; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + + if (!(obj instanceof JSONBoolean)) + return false; + + JSONBoolean other = (JSONBoolean) obj; + + return this.value == other.value; + } +} diff --git a/src/jsonlib/types/JSONDict.java b/src/jsonlib/types/JSONDict.java index 3650ffb..373c324 100644 --- a/src/jsonlib/types/JSONDict.java +++ b/src/jsonlib/types/JSONDict.java @@ -53,6 +53,14 @@ public int getInteger(String key) { return jsonNumber.getValue(); } + public boolean getBoolean(String key) { + JSONObject obj = this.get(key); + if (!(obj instanceof JSONBoolean)) + throw new IllegalArgumentException(String.format("dict[%s] is not a boolean", key)); + + return ((JSONBoolean) obj).getValue(); + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/src/jsonlib/types/JSONObject.java b/src/jsonlib/types/JSONObject.java index 8abc580..bb35885 100644 --- a/src/jsonlib/types/JSONObject.java +++ b/src/jsonlib/types/JSONObject.java @@ -22,6 +22,10 @@ public static JSONObject fromDict(Map da return new JSONDict(data); } + public static JSONObject fromBoolean(boolean data) { + return new JSONBoolean(data); + } + @Override public abstract String toString(); } diff --git a/src/model/Book.java b/src/model/Book.java index ddd15a1..a2e9b7a 100644 --- a/src/model/Book.java +++ b/src/model/Book.java @@ -1,32 +1,71 @@ package model; -public class Book { +import jsonlib.JSONSerializable; +import jsonlib.types.JSONObject; +import jsonlib.types.JSONDict; + +public class Book implements JSONSerializable { private String title; private String author; private String isbn; private int publicationYear; private boolean isBorrowed; - -//Constructor - public Book(String title,String author,String isbn,int publicationYear,boolean isBorrowed){ - this.title=title; - this.author=author; - this.isbn=isbn;this.publicationYear=publicationYear; - this.isBorrowed=isBorrowed; + // Constructor + public Book(String title, String author, String isbn, int publicationYear, boolean isBorrowed) { + this.title = title; + this.author = author; + this.isbn = isbn; + this.publicationYear = publicationYear; + this.isBorrowed = isBorrowed; } -//Setter + + // Setter public void borrowBook() { - this.isBorrowed=true; + this.isBorrowed = true; } public void returnBook() { - this.isBorrowed=false; - } -//Getter - public String getTitle() {return this.title;} - public String getAuthor() {return this.author;} - public String getIsbn() {return this.isbn;} - public Integer getPublicationYear() {return this.publicationYear;} - public boolean getIsBorrowed() {return this.isBorrowed;} + this.isBorrowed = false; + } + + // Getter + public String getTitle() { + return this.title; + } + + public String getAuthor() { + return this.author; + } + + public String getIsbn() { + return this.isbn; + } + + public Integer getPublicationYear() { + return this.publicationYear; + } + + public boolean getIsBorrowed() { + return this.isBorrowed; + } + + @Override + public JSONObject serialize() { + JSONDict result = new JSONDict(); + + result.put("class", JSONObject.fromString("Book")); + result.put("title", JSONObject.fromString(title)); + result.put("author", JSONObject.fromString(author)); + result.put("isbn", JSONObject.fromString(isbn)); + result.put("publicationYear", JSONObject.fromNumber(publicationYear)); + result.put("isBorrowed", JSONObject.fromBoolean(isBorrowed)); + + return result; + } + + public static Book deserialize(JSONDict json) { + return new Book(json.getString("title"), json.getString("author"), json.getString("isbn"), + json.getInteger("publicationYear"), json.getBoolean("isBorrowed")); + } } diff --git a/src/model/Category.java b/src/model/Category.java index e1e52ac..13cc009 100644 --- a/src/model/Category.java +++ b/src/model/Category.java @@ -1,18 +1,41 @@ package model; -public class Category { +import jsonlib.JSONSerializable; +import jsonlib.types.JSONObject; +import jsonlib.types.JSONDict; + +public class Category implements JSONSerializable { private String name; private String description; -//Constructor - public Category(String name,String description){ - this.name=name; - this.description=description; + + // Constructor + public Category(String name, String description) { + this.name = name; + this.description = description; } -//Getter + + // Getter public String getName() { - return this.name; + return this.name; } + public String getDescription() { - return this.description; + return this.description; + } + + @Override + public JSONObject serialize() { + JSONDict result = new JSONDict(); + + result.put("class", JSONObject.fromString("Book")); + result.put("name", JSONObject.fromString(name)); + result.put("description", JSONObject.fromString(description)); + + return result; + } + + + public static Category deserialize(JSONDict json) { + return new Category(json.getString("name"), json.getString("description")); } } diff --git a/src/model/GraduateStudent.java b/src/model/GraduateStudent.java index b11b94a..c94f859 100644 --- a/src/model/GraduateStudent.java +++ b/src/model/GraduateStudent.java @@ -1,24 +1,62 @@ package model; +import jsonlib.types.JSONObject; +import jsonlib.types.JSONDict; + public class GraduateStudent extends Student { private String supervisor; private String thesisTitle; + @Override public void getStudentDetails() { // TODO: Implement method 'getStudentDetails' for GraduateStudent. throw new UnsupportedOperationException("Unimplemented method 'getStudentDetails'"); } -public GraduateStudent(String studentId,String firstName,String lastName,String major,String supervisor,String thesisTitle) -{ - super(studentId, firstName, lastName, major); - this.supervisor=supervisor; - this.thesisTitle=thesisTitle; -} -//Getter -public String getSupervisor() {return supervisor;} -public String getThesisTitle() {return thesisTitle;} -//Setter -public void setSupervisor (String supervisor) {this.supervisor=supervisor;} -public void setThesisTitle(String thesisTitle) {this.thesisTitle=thesisTitle;} -} + public GraduateStudent(String studentId, String firstName, String lastName, String major, String supervisor, + String thesisTitle) { + super(studentId, firstName, lastName, major); + this.supervisor = supervisor; + this.thesisTitle = thesisTitle; + } + + // Getter + public String getSupervisor() { + return supervisor; + } + + public String getThesisTitle() { + return thesisTitle; + } + + // Setter + public void setSupervisor(String supervisor) { + this.supervisor = supervisor; + } + + public void setThesisTitle(String thesisTitle) { + this.thesisTitle = thesisTitle; + } + + @Override + public JSONObject serialize() { + JSONDict result = new JSONDict(); + + result.put("class", JSONObject.fromString("GraduateStudent")); + + result.put("studentId", JSONObject.fromString(studentId)); + result.put("firstName", JSONObject.fromString(firstName)); + result.put("lastName", JSONObject.fromString(lastName)); + result.put("major", JSONObject.fromString(major)); + + result.put("supervisor", JSONObject.fromString(supervisor)); + result.put("thesisTitle", JSONObject.fromString(thesisTitle)); + + return result; + } + + public static GraduateStudent deserialize(JSONDict json) { + return new GraduateStudent(json.getString("studentId"), json.getString("firstName"), json.getString("lastName"), + json.getString("major"), json.getString("supervisor"), json.getString("thesisTitle")); + } +} diff --git a/src/model/Loan.java b/src/model/Loan.java index eec35bc..e654c3d 100644 --- a/src/model/Loan.java +++ b/src/model/Loan.java @@ -2,32 +2,80 @@ import java.util.Date; -public class Loan { +import jsonlib.JSONSerializable; +import jsonlib.JSONSerializableFactory; +import jsonlib.types.JSONObject; +import jsonlib.types.JSONDict; +import jsonlib.types.JSONNumber; + +public class Loan implements JSONSerializable { private Book book; private Student student; private Date loanDate; private Date dueDate; + public Loan(Book book, Student student, Date loanDate, Date dueDate) { + this.book = book; + this.student = student; + this.loanDate = loanDate; + this.dueDate = dueDate; + } + + // Seterr + public void setBook(Book book) { + this.book = book; + } + + public void setStudent(Student student) { + this.student = student; + } + + public void setLoanDate(Date loanDate) { + this.loanDate = loanDate; + } + + public void setDueDate(Date dueDate) { + this.dueDate = dueDate; + } + + // getter + public Book getBook() { + return this.book; + } + + public Student getStudent() { + return this.student; + } + + public Date getLoanDate() { + return this.loanDate; + } + + public Date getDueDate() { + return this.dueDate; + } + @Override + public JSONObject serialize() { + JSONDict result = new JSONDict(); - public Loan(Book book,Student student,Date loanDate,Date dueDate){ - this.book=book; - this.student=student; - this.loanDate=loanDate; - this.dueDate=dueDate; + result.put("class", JSONObject.fromString("Loan")); + result.put("book", book.serialize()); + result.put("student", student.serialize()); + + result.put("loanDate", new JSONNumber(loanDate.getTime())); + result.put("dueDate", new JSONNumber(dueDate.getTime())); + return result; } + public static Loan deserialize(JSONDict json) { + JSONNumber loanDateValue = (JSONNumber) json.get("loanDate"); + JSONNumber dueDateValue = (JSONNumber) json.get("dueDate"); + Book book = (Book) JSONSerializableFactory.deserialize((JSONDict) json.get("book")); + Student student = (Student) JSONSerializableFactory.deserialize((JSONDict) json.get("student")); -//Seterr - public void setBook (Book book) {this.book=book;} - public void setStudent (Student student) {this.student=student;} - public void setLoanDate (Date loanDate) {this.loanDate=loanDate;} - public void setDueDate (Date dueDate) {this.dueDate=dueDate;} -//getter - public Book getBook() {return this.book;} - public Student getStudent() {return this.student;} - public Date getLoanDate() {return this.loanDate;} - public Date getDueDate() {return this.dueDate;} + return new Loan(book, student, new Date(loanDateValue.getValue()), new Date(dueDateValue.getValue())); + } } diff --git a/src/model/Student.java b/src/model/Student.java index be30326..6a2e2ad 100644 --- a/src/model/Student.java +++ b/src/model/Student.java @@ -1,26 +1,54 @@ package model; -public abstract class Student { - protected String studentId; - protected String firstName; - protected String lastName; - protected String major; -public Student(String studentId,String firstName,String lastName,String major){ - this.studentId=studentId; - this.firstName=firstName; - this.lastName=lastName; - this.major=major; -} +import jsonlib.JSONSerializable; + +public abstract class Student implements JSONSerializable { + protected String studentId; + protected String firstName; + protected String lastName; + protected String major; + + public Student(String studentId, String firstName, String lastName, String major) { + this.studentId = studentId; + this.firstName = firstName; + this.lastName = lastName; + this.major = major; + } + public abstract void getStudentDetails(); -//Setter - public void setStudentId (String studentId) {this.studentId=studentId;} - public void setFirstName (String firstName) {this.firstName=firstName;} - public void setLastName (String lastName) {this.lastName=lastName;} - public void setMajor (String major) {this.major=major;} -//Getter - public String getStudentId() {return this.studentId;} - public String getFirstName() {return this.firstName;} - public String getLastName() {return this.lastName;} - public String getMajor() {return this.major;} - -} \ No newline at end of file + + // Setter + public void setStudentId(String studentId) { + this.studentId = studentId; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public void setMajor(String major) { + this.major = major; + } + + // Getter + public String getStudentId() { + return this.studentId; + } + + public String getFirstName() { + return this.firstName; + } + + public String getLastName() { + return this.lastName; + } + + public String getMajor() { + return this.major; + } + +} diff --git a/src/model/UndergraduateStudent.java b/src/model/UndergraduateStudent.java index b7ff6b7..4fa8990 100644 --- a/src/model/UndergraduateStudent.java +++ b/src/model/UndergraduateStudent.java @@ -1,5 +1,8 @@ package model; +import jsonlib.types.JSONObject; +import jsonlib.types.JSONDict; + public class UndergraduateStudent extends Student { private int enrollmentYear; @@ -8,18 +11,40 @@ public void getStudentDetails() { // TODO: Implement method 'getStudentDetails' for UndergraduateStudent. throw new UnsupportedOperationException("Unimplemented method 'getStudentDetails'"); } - -public UndergraduateStudent(String studentId,String firstName,String lastName,String major,int enrollmentYear){ - super(studentId,firstName,lastName,major); - this.enrollmentYear=enrollmentYear; - } -//Getter -public int getEnrollmentYear(){ - return this.enrollmentYear; -} -//Setter -public void setEnrollmentYear(int enrollmentYear){ - this.enrollmentYear=enrollmentYear; -} + + public UndergraduateStudent(String studentId, String firstName, String lastName, String major, int enrollmentYear) { + super(studentId, firstName, lastName, major); + this.enrollmentYear = enrollmentYear; + } + + // Getter + public int getEnrollmentYear() { + return this.enrollmentYear; + } + + // Setter + public void setEnrollmentYear(int enrollmentYear) { + this.enrollmentYear = enrollmentYear; + } + + @Override + public JSONObject serialize() { + JSONDict result = new JSONDict(); + + result.put("class", JSONObject.fromString("UndergraduateStudent")); + + result.put("studentId", JSONObject.fromString(studentId)); + result.put("firstName", JSONObject.fromString(firstName)); + result.put("lastName", JSONObject.fromString(lastName)); + result.put("major", JSONObject.fromString(major)); + + result.put("enrollmentYear", JSONObject.fromNumber(enrollmentYear)); + return result; + } + + public static UndergraduateStudent deserialize(JSONDict json) { + return new UndergraduateStudent(json.getString("studentId"), json.getString("firstName"), + json.getString("lastName"), json.getString("major"), json.getInteger("enrollmentYear")); + } }