From 9efe1e5970997a14b88896ea99b794ac388be7cc Mon Sep 17 00:00:00 2001
From: "muhammad.dhafin01" <muhammad.dhafin01@ui.ac.id>
Date: Mon, 14 Feb 2022 20:45:35 +0700
Subject: [PATCH] Finished Task

---
 .../controller/CourseController.java          | 41 ++++++++++++++
 .../controller/StudentController.java         | 46 ++++++++++++++++
 .../DuplicateStudentNameException.java        |  8 +++
 .../ui/cs/advprog/tutorialo/model/Course.java | 11 ++++
 .../cs/advprog/tutorialo/model/Student.java   | 12 ++++
 .../repository/CourseRepository.java          | 24 ++++++++
 .../repository/StudentRepository.java         | 23 ++++++++
 .../tutorialo/service/CourseService.java      | 11 ++++
 .../tutorialo/service/CourseServiceImpl.java  | 55 +++++++++++++++++++
 .../service/MockStudentServiceImpl.java       | 22 ++++++++
 .../tutorialo/service/StudentService.java     | 11 ++++
 .../tutorialo/service/StudentServiceImpl.java | 55 +++++++++++++++++++
 src/main/resources/templates/courseList.html  | 34 ++++++++++++
 .../resources/templates/createCourse.html     | 30 ++++++++++
 .../resources/templates/createStudent.html    | 27 +++++++++
 src/main/resources/templates/studentList.html | 34 ++++++++++++
 16 files changed, 444 insertions(+)
 create mode 100644 src/main/java/id/ac/ui/cs/advprog/tutorialo/controller/CourseController.java
 create mode 100644 src/main/java/id/ac/ui/cs/advprog/tutorialo/controller/StudentController.java
 create mode 100644 src/main/java/id/ac/ui/cs/advprog/tutorialo/exception/DuplicateStudentNameException.java
 create mode 100644 src/main/java/id/ac/ui/cs/advprog/tutorialo/model/Course.java
 create mode 100644 src/main/java/id/ac/ui/cs/advprog/tutorialo/model/Student.java
 create mode 100644 src/main/java/id/ac/ui/cs/advprog/tutorialo/repository/CourseRepository.java
 create mode 100644 src/main/java/id/ac/ui/cs/advprog/tutorialo/repository/StudentRepository.java
 create mode 100644 src/main/java/id/ac/ui/cs/advprog/tutorialo/service/CourseService.java
 create mode 100644 src/main/java/id/ac/ui/cs/advprog/tutorialo/service/CourseServiceImpl.java
 create mode 100644 src/main/java/id/ac/ui/cs/advprog/tutorialo/service/MockStudentServiceImpl.java
 create mode 100644 src/main/java/id/ac/ui/cs/advprog/tutorialo/service/StudentService.java
 create mode 100644 src/main/java/id/ac/ui/cs/advprog/tutorialo/service/StudentServiceImpl.java
 create mode 100644 src/main/resources/templates/courseList.html
 create mode 100644 src/main/resources/templates/createCourse.html
 create mode 100644 src/main/resources/templates/createStudent.html
 create mode 100644 src/main/resources/templates/studentList.html

diff --git a/src/main/java/id/ac/ui/cs/advprog/tutorialo/controller/CourseController.java b/src/main/java/id/ac/ui/cs/advprog/tutorialo/controller/CourseController.java
new file mode 100644
index 0000000..4be5429
--- /dev/null
+++ b/src/main/java/id/ac/ui/cs/advprog/tutorialo/controller/CourseController.java
@@ -0,0 +1,41 @@
+package id.ac.ui.cs.advprog.tutorialo.controller;
+
+
+import id.ac.ui.cs.advprog.tutorialo.model.Course;
+import id.ac.ui.cs.advprog.tutorialo.service.CourseService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Controller
+@RequestMapping("/course")
+public class CourseController {
+
+    @Autowired
+    private CourseService service;
+
+    @GetMapping("/list")
+    public String courseListPage(Model model) {
+        List<Course> allCourse = service.findAll();
+        model.addAttribute("courses", allCourse);
+        return "courseList";
+    }
+
+    @GetMapping("/create")
+    public String createCoursePage(Model model) {
+        Course course = new Course();
+        model.addAttribute("course", course);
+        return "createCourse";
+    }
+
+    @PostMapping("/create")
+    public String createCoursePost(@ModelAttribute Course course, Model model) {
+        service.create(course);
+        return "redirect:list";
+    }
+
+}
+
diff --git a/src/main/java/id/ac/ui/cs/advprog/tutorialo/controller/StudentController.java b/src/main/java/id/ac/ui/cs/advprog/tutorialo/controller/StudentController.java
new file mode 100644
index 0000000..c31e257
--- /dev/null
+++ b/src/main/java/id/ac/ui/cs/advprog/tutorialo/controller/StudentController.java
@@ -0,0 +1,46 @@
+package id.ac.ui.cs.advprog.tutorialo.controller;
+
+import id.ac.ui.cs.advprog.tutorialo.exception.DuplicateStudentNameException;
+import id.ac.ui.cs.advprog.tutorialo.model.Student;
+import id.ac.ui.cs.advprog.tutorialo.service.StudentService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Controller
+@RequestMapping("/student")
+public class StudentController {
+
+    @Autowired
+    private StudentService service;
+
+    @GetMapping("/list")
+    public String studentListPage(Model model) {
+        List<Student> allStudents = service.findAll();
+        model.addAttribute("students", allStudents);
+        return "studentList";
+    }
+
+    @GetMapping("/create")
+    public String createStudentPage(Model model) {
+        Student student = new Student();
+        model.addAttribute("student", student);
+        return "createStudent";
+    }
+
+    @PostMapping("/create")
+    public String createStudentPost(@ModelAttribute Student student, Model model) {
+        try {
+            service.create(student);
+        } catch (DuplicateStudentNameException e) {
+            model.addAttribute("error", e);
+            model.addAttribute("student", student);
+            return "createStudent";
+        }
+        return "redirect:list";
+    }
+
+}
diff --git a/src/main/java/id/ac/ui/cs/advprog/tutorialo/exception/DuplicateStudentNameException.java b/src/main/java/id/ac/ui/cs/advprog/tutorialo/exception/DuplicateStudentNameException.java
new file mode 100644
index 0000000..69e2b98
--- /dev/null
+++ b/src/main/java/id/ac/ui/cs/advprog/tutorialo/exception/DuplicateStudentNameException.java
@@ -0,0 +1,8 @@
+package id.ac.ui.cs.advprog.tutorialo.exception;
+
+public class DuplicateStudentNameException extends RuntimeException {
+
+    public DuplicateStudentNameException(String studentName) {
+        super(String.format("The student name %s is a duplicate!",studentName));
+    }
+}
diff --git a/src/main/java/id/ac/ui/cs/advprog/tutorialo/model/Course.java b/src/main/java/id/ac/ui/cs/advprog/tutorialo/model/Course.java
new file mode 100644
index 0000000..1ab6eba
--- /dev/null
+++ b/src/main/java/id/ac/ui/cs/advprog/tutorialo/model/Course.java
@@ -0,0 +1,11 @@
+package id.ac.ui.cs.advprog.tutorialo.model;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter @Setter
+public class Course {
+    private String courseId;
+    private String courseName;
+    private Boolean vacancyStatus = Boolean.TRUE;
+}
diff --git a/src/main/java/id/ac/ui/cs/advprog/tutorialo/model/Student.java b/src/main/java/id/ac/ui/cs/advprog/tutorialo/model/Student.java
new file mode 100644
index 0000000..34178fd
--- /dev/null
+++ b/src/main/java/id/ac/ui/cs/advprog/tutorialo/model/Student.java
@@ -0,0 +1,12 @@
+package id.ac.ui.cs.advprog.tutorialo.model;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter @Setter
+public class Student {
+    private String name;
+    private String npm;
+    private String address;
+
+}
diff --git a/src/main/java/id/ac/ui/cs/advprog/tutorialo/repository/CourseRepository.java b/src/main/java/id/ac/ui/cs/advprog/tutorialo/repository/CourseRepository.java
new file mode 100644
index 0000000..305b77b
--- /dev/null
+++ b/src/main/java/id/ac/ui/cs/advprog/tutorialo/repository/CourseRepository.java
@@ -0,0 +1,24 @@
+package id.ac.ui.cs.advprog.tutorialo.repository;
+
+import id.ac.ui.cs.advprog.tutorialo.model.Course;
+import org.springframework.stereotype.Repository;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+@Repository
+public class CourseRepository {
+
+    private List<Course> coursesInMemory = new ArrayList<>();
+
+    public Course create(Course course){
+//        course.setVacancyStatus(Boolean.TRUE);
+        coursesInMemory.add(course);
+        return course;
+    }
+
+    public Iterator<Course> findAll(){
+        return coursesInMemory.iterator();
+    }
+}
diff --git a/src/main/java/id/ac/ui/cs/advprog/tutorialo/repository/StudentRepository.java b/src/main/java/id/ac/ui/cs/advprog/tutorialo/repository/StudentRepository.java
new file mode 100644
index 0000000..b225eb7
--- /dev/null
+++ b/src/main/java/id/ac/ui/cs/advprog/tutorialo/repository/StudentRepository.java
@@ -0,0 +1,23 @@
+package id.ac.ui.cs.advprog.tutorialo.repository;
+
+import id.ac.ui.cs.advprog.tutorialo.model.Student;
+import org.springframework.stereotype.Repository;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+@Repository
+public class StudentRepository {
+
+    private List<Student> studentsInMemory = new ArrayList<>();
+
+    public Student create(Student student){
+        studentsInMemory.add(student);
+        return student;
+    }
+
+    public Iterator<Student> findAll(){
+        return studentsInMemory.iterator();
+    }
+}
diff --git a/src/main/java/id/ac/ui/cs/advprog/tutorialo/service/CourseService.java b/src/main/java/id/ac/ui/cs/advprog/tutorialo/service/CourseService.java
new file mode 100644
index 0000000..bf16171
--- /dev/null
+++ b/src/main/java/id/ac/ui/cs/advprog/tutorialo/service/CourseService.java
@@ -0,0 +1,11 @@
+package id.ac.ui.cs.advprog.tutorialo.service;
+
+import id.ac.ui.cs.advprog.tutorialo.model.Course;
+
+
+import java.util.List;
+
+public interface CourseService {
+    public Course create(Course course);
+    public List<Course> findAll();
+}
diff --git a/src/main/java/id/ac/ui/cs/advprog/tutorialo/service/CourseServiceImpl.java b/src/main/java/id/ac/ui/cs/advprog/tutorialo/service/CourseServiceImpl.java
new file mode 100644
index 0000000..8c2da91
--- /dev/null
+++ b/src/main/java/id/ac/ui/cs/advprog/tutorialo/service/CourseServiceImpl.java
@@ -0,0 +1,55 @@
+package id.ac.ui.cs.advprog.tutorialo.service;
+
+
+import id.ac.ui.cs.advprog.tutorialo.model.Course;
+import id.ac.ui.cs.advprog.tutorialo.repository.CourseRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+@Service
+public class CourseServiceImpl implements CourseService {
+
+    @Autowired
+    private CourseRepository courseRepository;
+
+    @Override
+    public Course create(Course course) {
+//        course.setVacancyStatus(Boolean.TRUE);
+        generateId(course);
+        courseRepository.create(course);
+        return course;
+    }
+
+//    private void validateName(Student student) {
+//        List<Student> allStudents = findAll();
+//        for(Student dbStudent: allStudents) {
+//            if(dbStudent.getName().equals(student.getName())) {
+//                throw new DuplicateStudentNameException(student.getName());
+//            }
+//        }
+//
+//    }
+
+    private void generateId(Course course) {
+        StringBuilder stringBuilder = new StringBuilder();
+        for (char letter: course.getCourseName().toCharArray()) {
+            stringBuilder.append(String.valueOf((int)letter));
+        }
+        String courseId = stringBuilder.toString();
+        course.setCourseId(courseId);
+    }
+
+
+
+    @Override
+    public List<Course> findAll() {
+        Iterator<Course> courseIterator = courseRepository.findAll();
+        List<Course> allCourses = new ArrayList<>();
+        courseIterator.forEachRemaining(allCourses::add);
+        return allCourses;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/id/ac/ui/cs/advprog/tutorialo/service/MockStudentServiceImpl.java b/src/main/java/id/ac/ui/cs/advprog/tutorialo/service/MockStudentServiceImpl.java
new file mode 100644
index 0000000..bd26643
--- /dev/null
+++ b/src/main/java/id/ac/ui/cs/advprog/tutorialo/service/MockStudentServiceImpl.java
@@ -0,0 +1,22 @@
+package id.ac.ui.cs.advprog.tutorialo.service;
+
+
+
+import id.ac.ui.cs.advprog.tutorialo.model.Student;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class MockStudentServiceImpl implements StudentService{
+
+    @Override
+    public Student create(Student student) {
+        return null;
+    }
+
+    @Override
+    public List<Student> findAll() {
+        return null;
+    }
+}
diff --git a/src/main/java/id/ac/ui/cs/advprog/tutorialo/service/StudentService.java b/src/main/java/id/ac/ui/cs/advprog/tutorialo/service/StudentService.java
new file mode 100644
index 0000000..22783c7
--- /dev/null
+++ b/src/main/java/id/ac/ui/cs/advprog/tutorialo/service/StudentService.java
@@ -0,0 +1,11 @@
+package id.ac.ui.cs.advprog.tutorialo.service;
+
+import id.ac.ui.cs.advprog.tutorialo.model.Student;
+
+import java.util.List;
+
+public interface StudentService {
+    public Student create(Student student);
+    public List<Student> findAll();
+
+}
diff --git a/src/main/java/id/ac/ui/cs/advprog/tutorialo/service/StudentServiceImpl.java b/src/main/java/id/ac/ui/cs/advprog/tutorialo/service/StudentServiceImpl.java
new file mode 100644
index 0000000..7368cd2
--- /dev/null
+++ b/src/main/java/id/ac/ui/cs/advprog/tutorialo/service/StudentServiceImpl.java
@@ -0,0 +1,55 @@
+package id.ac.ui.cs.advprog.tutorialo.service;
+
+import id.ac.ui.cs.advprog.tutorialo.exception.DuplicateStudentNameException;
+import id.ac.ui.cs.advprog.tutorialo.model.Student;
+import id.ac.ui.cs.advprog.tutorialo.repository.StudentRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+@Service
+public class StudentServiceImpl implements StudentService {
+
+    @Autowired
+    private StudentRepository studentRepository;
+
+    @Override
+    public Student create(Student student) {
+        validateName(student);
+        generateNPM(student);
+        studentRepository.create(student);
+        return student;
+    }
+
+    private void validateName(Student student) {
+        List<Student> allStudents = findAll();
+        for(Student dbStudent: allStudents) {
+            if(dbStudent.getName().equals(student.getName())) {
+                throw new DuplicateStudentNameException(student.getName());
+            }
+        }
+
+    }
+
+    private void generateNPM(Student student) {
+        StringBuilder stringBuilder = new StringBuilder();
+        for (char letter: student.getName().toCharArray()) {
+            stringBuilder.append(String.valueOf((int)letter));
+        }
+        String npm = stringBuilder.toString();
+        student.setNpm(npm);
+    }
+
+
+
+    @Override
+    public List<Student> findAll() {
+        Iterator<Student> studentIterator = studentRepository.findAll();
+        List<Student> allStudents = new ArrayList<>();
+        studentIterator.forEachRemaining(allStudents::add);
+        return allStudents;
+    }
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/courseList.html b/src/main/resources/templates/courseList.html
new file mode 100644
index 0000000..dcf1837
--- /dev/null
+++ b/src/main/resources/templates/courseList.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html lang="en" xmlns:th="http://www.thymeleaf.org">
+<head>
+  <meta charset="UTF-8">
+  <title>Course List</title>
+  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
+</head>
+<body>
+
+<h2>Course' List</h2>
+<a th:href="@{/course/create}" class="btn btn-primary btn-sm mb-3" >Create course</a>
+
+<table class="table">
+  <thead>
+  <tr>
+    <th scope="col">Course Name</th>
+    <th scope="col">Course Id</th>
+    <th scope="col">Vacancy Status</th>
+  </tr>
+  </thead>
+  <tbody th:each="course: ${courses}">
+  <tr>
+    <td th:text="${course.courseName}"></td>
+    <td th:text="${course.courseId}"></td>
+    <td th:text="${course.vacancyStatus}"></td>
+  </tr>
+
+  </tbody>
+</table>
+
+
+<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
+</body>
+</html>
diff --git a/src/main/resources/templates/createCourse.html b/src/main/resources/templates/createCourse.html
new file mode 100644
index 0000000..001e88b
--- /dev/null
+++ b/src/main/resources/templates/createCourse.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html lang="en" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <meta charset="UTF-8">
+    <title>Create new Student</title>
+    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
+</head>
+<body>
+<h3>Create new Course</h3>
+<!--<div th:if="${error!=null}" class="alert alert-danger" role="alert">-->
+<!--    Duplicate student name-->
+<!--</div>-->
+<form th:action="@{/course/create}" th:object="${course}" method="post">
+    <div class="form-group">
+        <label for="nameInput">Name</label>
+        <input th:field="*{courseName}" type="text" class="form-control" id="nameInput" aria-describedby="nameHelp" placeholder="Enter course' name">
+        <small id="nameHelp" class="form-text text-muted">Please enter unique name.</small>
+    </div>
+    <div class="form-check">
+        <input th:field= "*{vacancyStatus} "class="form-check-input" type="checkbox" value="yes" id="flexCheckChecked">
+        <label class="form-check-label" for="flexCheckChecked">
+            Vacancy Status
+        </label>
+    </div>
+
+    <button type="submit" class="btn btn-primary">Submit</button>
+</form>
+<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
+</body>
+</html>
diff --git a/src/main/resources/templates/createStudent.html b/src/main/resources/templates/createStudent.html
new file mode 100644
index 0000000..30e4412
--- /dev/null
+++ b/src/main/resources/templates/createStudent.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="en" xmlns:th="http://www.thymeleaf.org">
+<head>
+  <meta charset="UTF-8">
+  <title>Create new Student</title>
+  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
+</head>
+<body>
+<h3>Create new Student</h3>
+<div th:if="${error!=null}" class="alert alert-danger" role="alert">
+  Duplicate student name
+</div>
+<form th:action="@{/student/create}" th:object="${student}" method="post">
+  <div class="form-group">
+    <label for="nameInput">Name</label>
+    <input th:field="*{name}" type="text" class="form-control" id="nameInput" aria-describedby="nameHelp" placeholder="Enter student' name">
+    <small id="nameHelp" class="form-text text-muted">Please enter unique name.</small>
+  </div>
+  <div class="form-group">
+    <label for="addressTextarea">Address</label>
+    <textarea th:field="*{address}" class="form-control" id="addressTextarea" rows="3"></textarea>
+  </div>
+  <button type="submit" class="btn btn-primary">Submit</button>
+</form>
+<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
+</body>
+</html>
diff --git a/src/main/resources/templates/studentList.html b/src/main/resources/templates/studentList.html
new file mode 100644
index 0000000..decee85
--- /dev/null
+++ b/src/main/resources/templates/studentList.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html lang="en" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <meta charset="UTF-8">
+    <title>Student List</title>
+    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
+</head>
+<body>
+
+<h2>Student' List</h2>
+<a th:href="@{/student/create}" class="btn btn-primary btn-sm mb-3" >Create student</a>
+
+<table class="table">
+    <thead>
+    <tr>
+        <th scope="col">Name</th>
+        <th scope="col">NPM</th>
+        <th scope="col">Address</th>
+    </tr>
+    </thead>
+    <tbody th:each="student: ${students}">
+    <tr>
+        <td th:text="${student.name}"></td>
+        <td th:text="${student.npm}"></td>
+        <td th:text="${student.address}"></td>
+    </tr>
+
+    </tbody>
+</table>
+
+
+<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
+</body>
+</html>
-- 
GitLab