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);
}
}