import java.util.*; /** * An Utility Validation class. */ final class Validation { /** Max size for names. */ private static final int MAX_SIZE = 20; /** Classroom name length. */ private static final int CLASSROOM_NAME_LENGTH = 2; /** Classroom min size. */ private static final int CLASSROOM_MIN_SIZE = 10; /** Classroom default/max size. */ public static final int CLASSROOM_MAX_SIZE = 30; /** Identity length. */ private static final int ID_LENGTH = 8; /** * No instance of this class are allowed. */ private Validation() { } /** * A {@code name} is valid if it is neither {@code null} nor empty and * not more than {@code MAX_SIZE}. * @param name a name * @return {@code true} if {@code name} is valid * @see MAX_SIZE */ public static boolean isNameValid(String name) { return name != null && !name.isBlank() && name.length() <= MAX_SIZE; } /** * A valid age is between 15 and 18 years old. * * @param inAge an age * @return {@code true} if {@code inAge} is between the limits */ public static boolean isAgeValid(int inAge) { return inAge >= 15 && inAge <= 18; } /** * A valid classroom size is between 10 and 30 pupils. * * @param inSize classroom size * @return {@code true} if {@code inSize} is between the limits * @see CLASSROOM_MIN_SIZE * @see CLASSROOM_MAX_SIZE */ public static boolean isSizeValid(int inSize) { return inSize >= CLASSROOM_MIN_SIZE && inSize <= CLASSROOM_MAX_SIZE; } /** * A valid classroom name should start with one of the letters {@code Α, Β, Γ} * and end with a number. E.g. {@code Γ1}. * @param classRoom a classroom name * @return {@code true} if {@code classRoom} is valid * @see CLASSROOM_NAME_LENGTH */ public static boolean isClassRoomNameValid(String classRoom) { return classRoom != null && !classRoom.isBlank() && classRoom.length() == CLASSROOM_NAME_LENGTH && (classRoom.startsWith("Α") || classRoom.startsWith("Β") || classRoom.startsWith("Γ")) && classRoom.charAt(1) >= '1' && classRoom.charAt(1) <= '9'; } /** * A valid Hellenic ID consists of two letters and six numbers. E.g. {@code XY123456}. * @param id a Hellenic ID number (ΑΔΤ) * @return {@code true} if the {@code id} is valid * @see ID_LENGTH */ public static boolean isIdValid(String id) { return id != null && !id.isBlank() && id.length() == ID_LENGTH && isCapitalLetter(id.charAt(0)) && isCapitalLetter(id.charAt(1)) && isNumber(id.charAt(2)) && isNumber(id.charAt(3)) && isNumber(id.charAt(4)) && isNumber(id.charAt(5)) && isNumber(id.charAt(6)) && isNumber(id.charAt(7)); } /** * Check if {@code c} is a capital letter. * @param c character to check * @return {@code true} if {@code c} is capital letter. */ public static boolean isCapitalLetter(char c) { return c >= 'A' && c <= 'Ω'; } /** * Check if {@code c} is a number. * @param c character to check * @return {@code true} if {@code c} is a number. */ public static boolean isNumber(char c) { return c >= '0' && c <= '9'; } } abstract class Person { /** The empty string used in case no name has been given. */ static final String NONE = "<Κενό>"; /** Person's first name. */ protected String firstName = NONE; /** Person's last name. */ protected String lastName = NONE; /** * Creates a new person. Is only called by subclasses. * * @param firstName first name * @param lastName last name * @see school.validation.Validation#isNameValid */ Person(String firstName, String lastName) { if (Validation.isNameValid(firstName)) { this.firstName = firstName.trim(); } if (Validation.isNameValid(lastName)) { this.lastName = lastName.trim(); } } /** * @return person's first name */ public String getFirstName() { return firstName; } /** * Set person's first name. * * @param firstName a new first name * @see school.validation.Validation#isNameValid */ public void setFirstName(String firstName) { this.firstName = Validation.isNameValid(firstName) ? firstName.trim() : NONE; } /** * @return person's last name */ public String getLastName() { return lastName; } /** * Set person's last name. * * @param lastName a new last name * @see school.validation.Validation#isNameValid */ public void setLastName(String lastName) { this.lastName = Validation.isNameValid(lastName) ? lastName.trim() : NONE; } @Override public String toString() { return ", firstName=" + firstName + ", lastName=" + lastName; } } /** * A student of the school. */ class Student extends Person { /** Automatic counter to set AM. */ private static int amCounter = 0; /** Student's registration number (AM).*/ private final int am; /** Student's age. -1 means age has not been set. */ private int age = -1; // 15-18 /** Student's classroom. */ private ClassRoom classRoom; /** * Constructor. * * @param firstName student's first name * @param lastName student's last name * @param age student's age must be between 15 and 18 years old * @see school.validation.Validation#isAgeValid(int) */ public Student(String firstName, String lastName, int age) { super(firstName, lastName); am = ++amCounter; if (Validation.isAgeValid(age)) { this.age = age; } } /** * Student's AM is calculated automatically. * @return student's AM */ public int getAm() { return am; } /** * @return student's age */ public int getAge() { return age; } /** * Set student's age. It increases every year. * @param age student's age. * @see school.validation.Validation#isAgeValid(int) */ public void setAge(int age) { this.age = Validation.isAgeValid(age) ? age : -1; } /** * @return the classroom the student is in. */ public ClassRoom getClassRoom() { return classRoom; } /** * Set student's classroom. * @param classRoom new classroom for student. */ void setClassRoom(ClassRoom classRoom) { this.classRoom = classRoom; } @Override public int hashCode() { int hash = 7; hash = 41 * hash + this.am; return hash; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Student other = (Student) obj; return this.am == other.am; } @Override public String toString() { return "Student{" + "am=" + am + super.toString() + ", age=" + age + ", classRoom=" + classRoom + '}'; } } /** * A school teacher. */ class Teacher extends Person { /** Max number of lessons a teacher can teach in the school. */ private static final int MAX_LESSONS = 3; /** No ID number. */ private String id = NONE; // ΑΔΤ /** Lessons the teacher can teach. */ private final Set<String> lessons; /** * Constructor. * * @param id teacher's ID number * @param firstName teacher's first name * @param lastName teacher's last name * @param lessons a teacher can teach up to 3 lessons * @see MAX_LESSONS * @see school.validation.Validation#isIdValid(java.lang.String) */ public Teacher(String id, String firstName, String lastName, String... lessons) { super(firstName, lastName); if (Validation.isIdValid(id)) { this.id = id; } if (lessons != null && lessons.length > 0) { // αντιγράφουμε μόνο τα 3 πρώτα μαθήματα int length = lessons.length > MAX_LESSONS ? MAX_LESSONS : lessons.length; this.lessons = new HashSet<>(Arrays.asList(Arrays.copyOfRange(lessons, 0, length))); } else { this.lessons = new HashSet<>(MAX_LESSONS); } } /** * @return the teacher's ID number */ public String getId() { return id; } /** * Set the teacher's id. * * @param id the new ID number. It shouldn't be null. * @see school.validation.Validation#isIdValid(java.lang.String) */ public void setId(String id) { this.id = Validation.isIdValid(id) ? id : NONE; } /** * Add a new lesson that this teacher teaches. If the number of lessons * that a teacher can teach is reached, the lesson is ignored. * @param lesson lesson to add */ public void addLesson(String lesson) { if (lesson != null && lessons.size() < MAX_LESSONS) { lessons.add(lesson); } } /** * Remove the lesson from the lessons that this teacher teaches. If the * lesson is not teached by this teacher, it is ignored. * @param lesson lesson to remove */ public void removeLesson(String lesson) { if (lesson != null) { this.lessons.remove(lesson); } } /** * Checks if the teacher teaches this lesson. * @param les lesson to search for * @return {@code true} if the teacher teaches this lesson. */ public boolean contains(String les) { return les == null ? false : this.lessons.contains(les); } /** * @return the lessons that this teacher teaches. */ public Collection<String> getLessons() { return Collections.unmodifiableCollection(this.lessons); } @Override public int hashCode() { int hash = 3; hash = 59 * hash + Objects.hashCode(this.id); return hash; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Teacher other = (Teacher) obj; return Objects.equals(this.id, other.id); } @Override public String toString() { return "Teacher{" + "id=" + id + super.toString() + ", lessons=" + lessons + '}'; } } /** * A classroom has a name, a size and contains students. */ class ClassRoom { /** Empty classroom name. */ private static final String NO_CLASSROOM = "--"; /** Classroom's name. */ private final String name; /** Classroom's size. */ private final int size; /** Classrooms' students. */ private final Set<Student> students; /** * Constructor. * * @param name classroom's name * @param size classroom's size * @see school.validation.Validation#isClassRoomNameValid(java.lang.String) * @see school.validation.Validation#isSizeValid(int) * @see school.validation.Validation#CLASSROOM_MAX_SIZE * @see NO_CLASSROOM */ public ClassRoom(String name, int size) { this.name = Validation.isClassRoomNameValid(name) ? name : NO_CLASSROOM; this.size = Validation.isSizeValid(size) ? size : Validation.CLASSROOM_MAX_SIZE; this.students = new HashSet<>(size); } /** * Constructor. Default size. * * @param name classroom's name. * @see school.validation.Validation#CLASSROOM_MAX_SIZE */ public ClassRoom(String name) { this(name, Validation.CLASSROOM_MAX_SIZE); } /** * @return classroom's name */ public String getName() { return name; } /** * @return classroom's size */ public int getSize() { return size; } /** * Add {@code student} to the class. * @param student to add */ public void addStudent(Student student) { if (student != null && students.size() < size) { students.add(student); student.setClassRoom(this); } } /** * Remove student with {@code am} from this class. * @param am student's reg. number. * @return the removed student */ public Student removeStudent(int am) { Student student = contains(am); if (removeStudent(student)) { student.setClassRoom(null); } return student; } /** * Remove {@code student} from this class. * * @param student student to remove from this class * @return {@code true} if student was removed successfully */ public boolean removeStudent(Student student) { boolean removed = false; if (student != null) { removed = students.remove(student); if (removed) { student.setClassRoom(null); } } return removed; } /** * Empty this class. */ public void removeAllStudents() { for (Student student : students) { student.setClassRoom(null); } students.clear(); } /** * Checks if the student is in this class. * @param am am of student to search for * @return {@code true} if the student with the given {@code am} exists in this class. */ public Student contains(int am) { for (Student student : students) { if (student.getAm() == am) { return student; } } return null; } /** * @return the students of this class. */ public Collection<Student> getStudents() { return Collections.unmodifiableCollection(students); } @Override public int hashCode() { int hash = 7; hash = 29 * hash + Objects.hashCode(this.name); return hash; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final ClassRoom other = (ClassRoom) obj; return Objects.equals(this.name, other.name); } @Override public String toString() { return "ClassRoom{" + "name=" + name + ", size=" + size + ", numOfStudents=" + students.size() + '}'; } } public class School { private static final ClassRoom[] classRooms = { new ClassRoom("Α1"), new ClassRoom("Α2", 28), new ClassRoom("Α3", 25), new ClassRoom("Β1"), new ClassRoom("Β2", 28), new ClassRoom("Β3", 25), new ClassRoom("Γ1"), new ClassRoom("Γ2", 26), new ClassRoom("Γ3", 22), }; public static void main(String[] args) { System.out.println("=== Create student ioannis ===="); Student ioannis = new Student("Γιάννης", "Αντεκοτούμπο", 16); System.out.println("AM: " + ioannis.getAm()); System.out.println("ClassRoom: " + ioannis.getClassRoom()); System.out.println("\n=== Add student ioannis to classroom 'B1' ===="); classRooms[3].addStudent(ioannis); System.out.println(ioannis.getClassRoom()); System.out.println(ioannis); System.out.println("\n=== Create student aliki and add to classroom 'B1' ===="); Student aliki = new Student("Αλίκη", "Βουγιουκλάκη", 17); classRooms[3].addStudent(aliki); System.out.println(aliki); System.out.println(classRooms[3]); System.out.println("\n=== Remove student ioannis from classroom 'B1' ===="); classRooms[3].removeStudent(ioannis.getAm()); System.out.println(ioannis); System.out.println(classRooms[3]); System.out.println("\n=== Create a teacher ===="); Teacher socrates = new Teacher("AB123456", "Σωκράτης", "Σωκράτης"); socrates.addLesson("Φιλοσοφία"); socrates.addLesson("Αρχαία Ελληνικά"); System.out.println(socrates); } }