Commit c6489acf authored by Georgi Cholev's avatar Georgi Cholev
Browse files

Add first version of student-management following gradle lecture

1 merge request!1Add first version of student-management following gradle lecture
Pipeline #1394 canceled with stages
in 0 seconds
Showing with 626 additions and 0 deletions
+626 -0
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# Linux start script should use lf
/gradlew text eol=lf
# These are Windows script files and should use crlf
*.bat text eol=crlf
# Ignore Gradle project-specific cache directory
.gradle
# Ignore Gradle build output directory
build
# Default ignored files
/shelf/
/workspace.xml
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="17" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<compositeConfiguration>
<compositeBuild compositeDefinitionSource="SCRIPT">
<builds>
<build path="$PROJECT_DIR$/buildSrc" name="buildSrc">
<projects>
<project path="$PROJECT_DIR$/buildSrc" />
</projects>
</build>
</builds>
</compositeBuild>
</compositeConfiguration>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="#JAVA_HOME" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/api" />
<option value="$PROJECT_DIR$/buildSrc" />
<option value="$PROJECT_DIR$/core" />
<option value="$PROJECT_DIR$/data" />
<option value="$PROJECT_DIR$/models" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="Gradle Central Plugin Repository" />
<option name="name" value="Gradle Central Plugin Repository" />
<option name="url" value="https://plugins.gradle.org/m2" />
</remote-repository>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="1.8.10" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK" />
<component name="SuppressKotlinCodeStyleNotification">
<option name="disableForAll" value="true" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>
\ No newline at end of file
/*
* This file was generated by the Gradle 'init' task.
*/
plugins {
id("student.management.java-application-conventions")
}
dependencies {
implementation(project(":models"))
implementation(project(":core"))
// https://mvnrepository.com/artifact/com.google.code.gson/gson
implementation("com.google.code.gson:gson:2.9.0")
}
application {
// Define the main class for the application.
mainClass.set("student.management.api.App")
}
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package student.management.api;
import student.management.api.runners.AppRunner;
import student.management.api.runners.impl.ConsoleAppRunner;
import student.management.core.services.in_memory_services.InMemoryServiceInitializer;
public class App {
public static void main(String[] args) {
AppRunner appRunner = new ConsoleAppRunner(new InMemoryServiceInitializer());
appRunner.handleRequests();
}
}
package student.management.api.runners;
public interface AppRunner {
void handleRequests();
void showOptions();
}
package student.management.api.runners.impl;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import student.management.api.runners.AppRunner;
import student.management.core.exc.ConflictingRequestParametersException;
import student.management.core.exc.InvalidEntityArgumentsException;
import student.management.core.exc.UnidentifiableEntityException;
import student.management.core.services.CourseService;
import student.management.core.services.GradeService;
import student.management.core.services.StudentService;
import student.management.core.services.TeacherService;
import student.management.core.services.in_memory_services.InMemoryServiceInitializer;
import student.management.models.dtos.create_dto.CourseCreateDto;
import student.management.models.dtos.create_dto.StudentCreateDto;
import student.management.models.dtos.create_dto.TeacherCreateDto;
import student.management.models.dtos.response_dto.CourseResponseDto;
import student.management.models.dtos.response_dto.StudentResponseDto;
import student.management.models.dtos.response_dto.TeacherResponseDto;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.function.Supplier;
public class ConsoleAppRunner implements AppRunner {
private static final int FUNCTIONALITIES_COUNT = 8;
private final CourseService courseService;
private final StudentService studentService;
private final TeacherService teacherService;
private final GradeService gradeService;
private final Scanner scanner;
private final Gson gson;
private final List<Supplier<String>> options;
private final List<String> optionTitles;
private final List<String> optionParameters;
public ConsoleAppRunner(InMemoryServiceInitializer serviceInitializer) {
this.courseService = serviceInitializer.getCourseService();
this.studentService = serviceInitializer.getStudentService();
this.teacherService = serviceInitializer.getTeacherService();
this.gradeService = serviceInitializer.getGradeService();
this.scanner = new Scanner(System.in);
this.gson = new GsonBuilder().setPrettyPrinting().create();
this.options = new ArrayList<>();
this.optionTitles = new ArrayList<>();
this.optionParameters = new ArrayList<>();
this.setUpAllFunc();
}
@Override
public void handleRequests() {
this.showOptions();
String input;
while (!(input = scanner.nextLine()).equals("End")) {
int commandIndex;
try {
commandIndex = Integer.parseInt(input);
} catch (NumberFormatException e) {
System.out.println("Please select a number from the menu");
this.showOptions();
continue;
}
if (commandIndex < 0 || commandIndex >= this.options.size()) {
System.out.println("Please select a number from the menu");
this.showOptions();
continue;
}
if (commandIndex == this.options.size() - 1) {
break;
}
this.showParameters(commandIndex);
System.out.println(this.options.get(commandIndex).get());
this.showOptions();
}
}
private String addNewCourse() {
String[] components = scanner.nextLine().split("/");
String name = components[0];
int totalHours = Integer.parseInt(components[1]);
String response;
try {
CourseResponseDto course = this.courseService.create(new CourseCreateDto(name, totalHours));
response = this.gson.toJson(course);
} catch (InvalidEntityArgumentsException e) {
response = e.getMessage();
}
return response;
}
private String addNewStudent() {
String[] components = scanner.nextLine().split("/");
String name = components[0];
int age = Integer.parseInt(components[1]);
String response;
try {
StudentResponseDto student = this.studentService.create(new StudentCreateDto(name, age));
response = this.gson.toJson(student);
} catch (InvalidEntityArgumentsException e) {
response = e.getMessage();
}
return response;
}
private String addNewTeacher() {
String[] components = scanner.nextLine().split("/");
String name = components[0];
String degree = components[1];
String response;
try {
TeacherResponseDto teacher = this.teacherService.create(new TeacherCreateDto(name, degree));
response = this.gson.toJson(teacher);
} catch (InvalidEntityArgumentsException e) {
response = e.getMessage();
}
return response;
}
private String addTeacherToCourse() {
String[] components = scanner.nextLine().split("/");
long courseId = Long.parseLong(components[0]);
long teacherId = Long.parseLong(components[1]);
String response;
try {
response = this.courseService.addTeacherTo(courseId, teacherId);
} catch (UnidentifiableEntityException e) {
response = e.getMessage();
}
return response;
}
private String removeTeacherFromCourse() {
String[] components = scanner.nextLine().split("/");
long courseId = Long.parseLong(components[0]);
String response;
try {
response = this.courseService.removeTeacherFor(courseId);
} catch (UnidentifiableEntityException e) {
response = e.getMessage();
}
return response;
}
private String addStudentToCourse() {
String[] components = scanner.nextLine().split("/");
long courseId = Long.parseLong(components[0]);
long studentId = Long.parseLong(components[1]);
String response;
try {
response = this.courseService.addStudentTo(courseId, studentId);
} catch (UnidentifiableEntityException e) {
response = e.getMessage();
}
return response;
}
private String addGradeForStudentInCourse() {
String[] components = scanner.nextLine().split("/");
long courseId = Long.parseLong(components[0]);
long studentId = Long.parseLong(components[1]);
double grade = Double.parseDouble(String.format("%.2f", Double.parseDouble(components[2])));
String response;
try {
response = this.courseService.addGradeForStudentIn(courseId, studentId, grade);
} catch (UnidentifiableEntityException | InvalidEntityArgumentsException |
ConflictingRequestParametersException e) {
response = e.getMessage();
}
return response;
}
private String showStudentsWithAvgGradeForCourse() {
long courseId = Long.parseLong(scanner.nextLine());
String response;
try {
response = this.gson.toJson(this.courseService.findAvgGradeFor(courseId));
} catch (UnidentifiableEntityException e) {
response = e.getMessage();
}
return response;
}
private String showCoursesWithTeacherAndStudents() {
return this.gson.toJson(this.courseService.findAll());
}
private String showStudentsGroupedByCourseAscWithAvgGradeAsc() {
return this.gson.toJson(this.courseService.findCoursesByNameAsc_WithStudentsAvgGradeAsc());
}
private String showAvgGradeForStudent() {
long studentId = Long.parseLong(scanner.nextLine());
String response;
try {
response = this.gson.toJson(this.studentService.getStudentWithAvgGrade(studentId));
} catch (UnidentifiableEntityException e) {
response = e.getMessage();
}
return response;
}
public String closeRunner() {
scanner.close();
return "End";
}
@Override
public void showOptions() {
System.out.println(String.join(System.lineSeparator(), this.optionTitles));
}
private void showParameters(int i) {
System.out.println(this.optionParameters.get(i));
}
private void setUpAllFunc() {
int counter = 0;
this.setUpFunc(counter++, "Add new course", "{name}/{totalHours}", this::addNewCourse);
this.setUpFunc(counter++, "Add new student", "{name}/{age}", this::addNewStudent);
this.setUpFunc(counter++, "Add new teacher", "{name}/{degree} -> (Master, Bachelor, Doctorate)", this::addNewTeacher);
this.setUpFunc(counter++, "Add a teacher to a specific course", "{courseId}/{teacherId}", this::addTeacherToCourse);
this.setUpFunc(counter++, "Remove a teacher from a specific course", "{courseId}", this::removeTeacherFromCourse);
this.setUpFunc(counter++, "Add a student to a specific course", "{courseId}/{studentId}", this::addStudentToCourse);
this.setUpFunc(counter++, "Add a grade for a student in a specific course", "{courseId}/{studentId}/{grade} -> between 2.0 and 6.0", this::addGradeForStudentInCourse);
this.setUpFunc(counter++, "Show all students grouped by course alphabetically and then by their average grade for the course ascending", "", this::showStudentsGroupedByCourseAscWithAvgGradeAsc);
this.setUpFunc(counter++, "Show all courses and their teachers and students", "", this::showCoursesWithTeacherAndStudents);
this.setUpFunc(counter++, "Show the average grade for all students in a specific course", "{courseId}", this::showStudentsWithAvgGradeForCourse);
this.setUpFunc(counter++, "Show a total average grade for a student", "{studentId}", this::showAvgGradeForStudent);
this.setUpFunc(counter++, "End", "", this::closeRunner);
}
private void setUpFunc(int index, String title, String parameters, Supplier<String> supplier) {
this.options.add(supplier);
this.optionTitles.add(index + "." + title);
this.optionParameters.add(parameters);
}
}
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package student.management.api;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class MessageUtilsTest {
@Test void testGetMessage() {
assertEquals("Hello World!", MessageUtils.getMessage());
}
}
/*
* This file was generated by the Gradle 'init' task.
*/
plugins {
// Support convention plugins written in Kotlin. Convention plugins are build scripts in 'src/main' that automatically become available as plugins in the main build.
`kotlin-dsl`
}
repositories {
// Use the plugin portal to apply community plugins in convention plugins.
gradlePluginPortal()
}
/*
* This file was generated by the Gradle 'init' task.
*
* This settings file is used to specify which projects to include in your build-logic build.
*/
rootProject.name = "buildSrc"
/*
* This file was generated by the Gradle 'init' task.
*/
plugins {
// Apply the common convention plugin for shared build configuration between library and application projects.
id("student.management.java-common-conventions")
// Apply the application plugin to add support for building a CLI application in Java.
application
}
/*
* This file was generated by the Gradle 'init' task.
*/
plugins {
// Apply the java Plugin to add support for Java.
java
}
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}
dependencies {
constraints {
// Define dependency versions as constraints
implementation("org.apache.commons:commons-text:1.10.0")
}
// Use JUnit Jupiter for testing.
testImplementation("org.junit.jupiter:junit-jupiter:5.9.1")
}
tasks.named<Test>("test") {
// Use JUnit Platform for unit tests.
useJUnitPlatform()
}
/*
* This file was generated by the Gradle 'init' task.
*/
plugins {
// Apply the common convention plugin for shared build configuration between library and application projects.
id("student.management.java-common-conventions")
// Apply the java-library plugin for API and implementation separation.
`java-library`
}
/*
* This file was generated by the Gradle 'init' task.
*/
plugins {
id("student.management.java-library-conventions")
}
dependencies {
implementation(project(":models"))
implementation(project(":data"))
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment